How to get enum type in a T4 template
在编写一个t4文本模板的过程中,我遇到了一个问题,我很难通过。我需要知道我正在处理的枚举的类型。
我有基于
这是byte类型的枚举示例
1 2 3 4 5 6 7 8 | namespace CodeEnumType { public enum MyEnum : byte { Member1 = 0, Member2 = 1, } } |
这是我的t4文本模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | <#@ 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; } } } #> |
注意我写的部分
1 2 3 | // // here I would like the enum type // |
这里我在变量
我没有在这里将反射用作类型。如果程序集尚未编译,getType()将无法正常工作。
envdte对象模型未公开基础枚举类型。作为解决方法,可以检索枚举类型定义的源代码并解析基类型,例如使用正则表达式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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; } } |
请注意,示例中的regex只是一个非常简单的模式,可能需要调整它来处理不同的源代码格式。
此方法应返回您要查找的内容。
1 2 3 4 5 | static Type GetEnumType<T>() where T : struct, IComparable { var ti = (TypeInfo)typeof(T); return ti.DeclaredFields.First().FieldType; } |
希望这有帮助;)