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