在编写T4文本模板的过程中,我遇到了一个我正在努力解决的问题。我需要知道我正在处理的枚举的类型。
我的枚举基于byte
和ushort
。我需要T4文本模板来编写代码以将枚举转换为正确的值类型,以便序列化枚举并将其放入字节数组中。
这是类型为byte
的枚举示例namespace CodeEnumType
{
public enum MyEnum : byte
{
Member1 = 0,
Member2 = 1,
}
}
这是我的T4文字模板
<#@ 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;
}
}
}
#>
注意我写的部分
//
// here I would like the enum type
//
这里我在变量codeEnum
中有我的枚举信息,这就是我的问题所在。如何从byte
获取ushort
或codeEnum
类型?
我在这里没有使用Reflection,因为如果程序集尚未编译,Type.GetType()不能正常工作。
答案 0 :(得分:8)
EnvDTE对象模型未公开底层枚举类型。作为工作区,您可以检索枚举类型定义的源代码并解析出基本类型,例如:使用正则表达式:
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;
}
}
请注意,示例中的正则表达式只是一个非常简单的模式,可能需要进行调整以应对不同的源代码格式。
答案 1 :(得分:2)
此方法应返回您要查找的内容。
static Type GetEnumType<T>() where T : struct, IComparable
{
var ti = (TypeInfo)typeof(T);
return ti.DeclaredFields.First().FieldType;
}
希望这会有所帮助;)