In the process of writing a T4 text template I ran into an issue I'm struggling to get by. I need to know the type of the enum I'm processing.
I have enums that are based on byte
and ushort
. I need the T4 text template to write code to cast the enum to the correct value type in order to serialize the enum and put it into a byte array.
This is an example enum of type byte
namespace CodeEnumType
{
public enum MyEnum : byte
{
Member1 = 0,
Member2 = 1,
}
}
And this is my T4 text template
<#@ template hostspecific="true" language="C#" #>
<#@ output extension=".cs" #>
<#@ assembly name="EnvDte" #>
<#@ import namespace="EnvDTE" #>
<#@ import namespace="System.Collections.Generic" #>
<#
var serviceProvider = this.Host as IServiceProvider;
var dte = serviceProvider.GetService(typeof(DTE)) as DTE;
var project = dte.Solution.FindProjectItem(this.Host.TemplateFile).ContainingProject as Project;
var projectItems = GetProjectItemsRecursively(project.ProjectItems);
foreach(var projectItem in projectItems)
{
var fileCodeModel = projectItem.FileCodeModel;
if(fileCodeModel == null)
{
continue;
}
CodeElements codeElements = fileCodeModel.CodeElements;
ProcessCodeElements(codeElements);
}
#>
<#+
public void ProcessCodeElements(CodeElements codeElements)
{
if(codeElements == null)
{
return;
}
foreach(CodeElement codeElement in codeElements)
{
switch(codeElement.Kind)
{
case vsCMElement.vsCMElementNamespace:
CodeNamespace codeNamespace = codeElement as CodeNamespace;
CodeElements childCodeElements = codeNamespace.Members;
ProcessCodeElements(childCodeElements);
break;
case vsCMElement.vsCMElementEnum:
CodeEnum codeEnum = codeElement as CodeEnum;
WriteLine(codeEnum.Name);
//
// here I would like the enum type
//
break;
}
}
}
public IEnumerable<ProjectItem> GetProjectItemsRecursively(ProjectItems items)
{
if(items == null)
{
yield break;
}
foreach(ProjectItem item in items)
{
yield return item;
var childItems = GetProjectItemsRecursively(item.ProjectItems);
foreach(ProjectItem childItem in childItems)
{
yield return childItem;
}
}
}
#>
Notice the part where I wrote
//
// here I would like the enum type
//
Here I have my enum information in the variable codeEnum
and this is where my problem is. How do I get byte
or ushort
type from codeEnum
?
I'm not using Reflection here as Type.GetType() does not work well if the assembly have not been compiled.
The underlying enum type is not exposed by the EnvDTE object model. As a workaroud, you can retrieve the source code of the enum type definition and parse out the base type, e.g. using a regular expression:
foreach(CodeElement codeElement in codeElements)
{
switch(codeElement.Kind)
{
case vsCMElement.vsCMElementNamespace:
CodeNamespace codeNamespace = codeElement as CodeNamespace;
CodeElements childCodeElements = codeNamespace.Members;
ProcessCodeElements(childCodeElements);
break;
case vsCMElement.vsCMElementEnum:
CodeEnum codeEnum = codeElement as CodeEnum;
Write(codeEnum.Name);
// get the source code of the enum
string sourceCodeEnum =
codeEnum.StartPoint.CreateEditPoint().GetText(codeEnum.EndPoint);
// a regular expression capturing the base type
System.Text.RegularExpressions.Regex regex
= new System.Text.RegularExpressions.Regex(
@"\benum .*\s*\:\s*(?<underlyingType>\w*)");
var match = regex.Match(sourceCodeEnum);
if (match.Success)
{
WriteLine(" : " + match.Groups["underlyingType"].Value);
}
break;
}
}
Note that the regex in the sample is just a very simple pattern that might need to be adjusted to cope with different source code formatting.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With