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.
CodeEnum
? What code generation technique are you actually using — T4 or CodeDom? Seems like a bizzare mixture assumingCode*
refer to CodeDom classes. – RichmalEnvDTE.CodeEnum
type. So he asks how to get the underlying integer type from that, I think. – Koonsforeach (var b in codeEnum.Bases) { WriteLine(b); }
or similar give you? I suspect the "underlying type" is to be found through the.Bases
property. – Koons.BaseType
during reflection then. Then reason why I had thought it might work was because theAddBase
method spec said something like: ForCodeEnum
objects,Base
is a variant containing a fully qualified type name orCodeType
object upon which the new enum is based. For C#, this is the underlying type of enum. Not that I know very much about this. – KoonsType.GetEnumUnderlyingType()
and it looks at the type of the first enum member. I tried that before without any luck, but maybe I should try that again. – Viscosevalue__
and holds the underlying integer value. This is not the first of the "enumeration constants" defined by the type (these are static, and there may be zero enumeration constants). So what that method does is equivalent to (reflection):.GetField("value__").FieldType
which actually works! I once wondered about this instance field in another question, Are .NET enum types actually mutable value types? – KoonsType.GetType(codeEnum.FullName).GetEnumUnderlyingType()
? – Koons