微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 生成枚举的JavaScript表示形式

我的代码中有几个[Flags]枚举,我想要暴露给 JavaScript而无需复制和粘贴. SignalR似乎正在通过将URL映射到一个Action来返回由反射生成的JavaScript存根来执行类似于Hub代理的操作.由于代码在运行时生成,所以似乎无法将其包含在Bundle中.

作为替代,我在设计时实现了一个T4模板来生成一个js文件

<#@ 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),},};

有没有更清洁的方法来实现这一点?理想地,某种设计时反射来生成js文件,因此可用于捆绑.

解决方法

我想你可以使用Bundle Transforms来完成这个…

http://www.asp.net/mvc/tutorials/mvc-4/bundling-and-minification

您可以定义一个bundle并附加一个IBundleTransform类,该类插入源文件内容.您应该能够使用反射来将JavaScript写入输出流.

如果你想以一种奇怪的方式来做,这将是相当容易做到的.你可以给它一个文件,并硬编码你的类使用反射来写你想要的JavaScript.

现在,如果您想要以不需要修改IBundleTransform类的方式进行设计,以便为您的JavaScript输出添加额外的枚举,则需要将一些额外的工作放入真实的结构中.例如,假设你有一个名为Enums.cs的文件,你可以把该文件添加到你的bundle的Include列表中,你可以动态地解析它的枚举声明,然后使用反射按名称找到它们在结果的JavaScript文件输出一个.

原文地址:https://www.jb51.cc/csharp/94820.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐