我的代码中有几个[Flags]枚举,我想要暴露给
JavaScript而无需复制和粘贴. SignalR似乎正在通过将URL映射到一个Action来返回由反射生成的JavaScript存根来执行类似于Hub代理的操作.由于代码在运行时生成,所以似乎无法将其包含在Bundle中.
<#@ template debug="false" hostspecific="true" language="C#" #> <#@ assembly name="System.Core" #> <#@ assembly name="EnvDte" #> <#@ import namespace="EnvDTE" #> <#@ import namespace="System.Linq" #> <#@ import namespace="System.Text" #> <#@ import namespace="System.Collections.Generic" #> <#@ output extension=".js" #> Enums = { <# var visualStudio = (Host as IServiceProvider).GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE; var project = visualStudio.Solution.FindProjectItem(this.Host.TemplateFile) .ContainingProject as EnvDTE.Project; foreach(EnvDTE.ProjectItem item in GetProjectItemsRecursively(project.ProjectItems)) { if (item.FileCodeModel == null) continue; foreach(EnvDTE.CodeElement elem in item.FileCodeModel.CodeElements) { if (elem.Kind == EnvDTE.vsCMElement.vsCMElementNamespace) { foreach (CodeElement innerElement in elem.Children) { if (innerElement.Kind == vsCMElement.vsCMElementEnum) { CodeEnum enu = (CodeEnum)innerElement; #> <#= enu.Name #>: { <# Dictionary<string,string> values = new Dictionary<string,string>(); foreach (CodeElement child in enu.Members) { CodeVariable value = child as CodeVariable; if (value != null) { string init = value.InitExpression as string; int unused; if (!int.TryParse(init,out unused)) { foreach (KeyValuePair<string,string> entry in values) { init = init.Replace(entry.Key,entry.Value); } init = "(" + init + ")"; } values.Add(value.Name,init); WriteLine("\t\t" + value.Name + ": " + init + ","); } } #> },<# } } } } } #> }; <#+ public List<EnvDTE.ProjectItem> GetProjectItemsRecursively(EnvDTE.ProjectItems items) { var ret = new List<EnvDTE.ProjectItem>(); if (items == null) return ret; foreach(EnvDTE.ProjectItem item in items) { ret.Add(item); ret.AddRange(GetProjectItemsRecursively(item.ProjectItems)); } return ret; } #>
然而,EnvDTE感觉很脆弱.特别是处理枚举的逻辑,如:
[Flags] public enum Access { None = 0,Read = 1,Write = 2,ReadWrite = Read | Write }
复合值是带有字符串替换的脏黑客.上面的T4模板会产生:
Enums = { Access: { None: 0,Read: 1,Write: 2,ReadWrite: (1 | 2),},};
解决方法
我想你可以使用Bundle Transforms来完成这个…
http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification
您可以定义一个bundle并附加一个IBundleTransform类,该类插入源文件的内容.您应该能够使用反射来将JavaScript写入输出流.
如果你想以一种奇怪的方式来做,这将是相当容易做到的.你可以给它一个空文件,并硬编码你的类使用反射来写你想要的JavaScript.
现在,如果您想要以不需要修改IBundleTransform类的方式进行设计,以便为您的JavaScript输出添加额外的枚举,则需要将一些额外的工作放入真实的结构中.例如,假设你有一个名为Enums.cs的文件,你可以把该文件添加到你的bundle的Include列表中,你可以动态地解析它的枚举声明,然后使用反射按名称找到它们在结果的JavaScript文件中输出每一个.