【问题标题】:Using anonymous types with T4 Templates for class generation使用带有 T4 模板的匿名类型来生成类
【发布时间】:2016-09-05 09:53:42
【问题描述】:

我想根据枚举值生成一堆类似的类。这些类在结构上将密切相关,但由于 C# 的类型安全性,使用继承来解决这个问题并不可行。因此,最好使用 T4。就我而言,我想在我的元编程代码中使用匿名类型。

这是一个最小的 sn-p,目的是说明我的使用模式,同时也说明了我遇到的问题:

using System;
using System.Windows.Data;
using System.Globalization;
using System.Windows;
using Fin4.Controls.Core;

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<#
    var enum_values = new dynamic[] {
        new { EnumName = "HoverDatePicker.Mode", Value = "View"},
        new { EnumName = "HoverDatePicker.Mode", Value = "Mode"},
        new { EnumName = "Frequency", Value = "Monthly"},
        new { EnumName = "Frequency", Value = "Weekly"}
    };
#>
<#
for(int i = 0; i < enum_values.Length; i++)
{ #>
    public class <#= enum_values[i].Value #>VisibilityConverter : IValueConverter
    {
    }
<# 
} #>

这保存在名为example.tt 的文件中。为此文件选择的自定义工具是TextTemplatingFileGenerator。当我(尝试)编译我的解决方案时,会生成以下输出:

ErrorGeneratingOutput

还会产生以下错误:

Severity    Code    Description Project File    Line    Suppression State
Error   CS0116  A namespace cannot directly contain members such as fields or methods   Fin4    x:\code\project\project\Controls\example.cs 1   Active
Error   CS0103  The name 'ErrorGeneratingOutput' does not exist in the current context. Fin4    x:\code\project\project\Controls\example.cs 1   Active
Error       Compiling transformation: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'   Fin4    X:\code\project\project\Controls\example.tt 25  

我第一次尝试解决这个问题是添加对Microsoft.CSharp 的引用。我的参考指向以下 dll:

C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\Microsoft.CSharp.dll

这并没有解决问题。我第二次尝试解决这个问题是将自定义工具设置更改为TextTemplatingFilePreprocessor。这产生了一个似乎与我想要的完全不同的文件,所以这也没有解决问题。

似乎很明显,有些东西阻止了TextTemplatingFileGenerator 工具使用 C# .NET 4.0 的匿名输入功能。但我不清楚如何启用它。我已经做了很多谷歌搜索,但似乎没有其他人有这个问题。

如果有人可以帮助我弄清楚如何将匿名类型与 T4 类生成器一起使用,那将非常有帮助。所以提前谢谢大家!

【问题讨论】:

    标签: c#-4.0 t4 anonymous-types


    【解决方案1】:

    我最终通过明确指定 C# 4.0 应该用于元编程来完成这项工作:

    <# // Specify the C# version being used is 4.0 #>
    <#@ Assembly Name="System.Core, Version=4.0.0.0, Culture=neutral" #>
    <#@ Assembly Name="Microsoft.CSharp, Version=4.0.0.0, Culture=neutral" #>
    
    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ output extension=".cs" #>
    <#
        var enum_nvs = new dynamic[] {
            new { EnumName = "HoverDatePicker.Mode",    EnumValue = "View"},
            new { EnumName = "HoverDatePicker.Mode",    EnumValue = "Edit"},
            new { EnumName = "Frequency",               EnumValue = "Monthly"},
            new { EnumName = "Frequency",               EnumValue = "Weekly"}
        };
    #>
    <#
    for(int i = 0; i < enum_values.Length; i++)
    { #>
        public class <#= enum_values[i].Value #>VisibilityConverter : IValueConverter
        {
        }
    <# 
    } #>
    

    【讨论】:

    • 有趣有帮助的答案,但问题不同。您的回答显示了如何使用 T4 中的“动态”。您的问题可以通过不使用“动态”来解决。您可能想修改您的问题或答案。 (顺便说一句,您的答案有错别字,不会按书面形式编译:enum_nvs != enum_values)
    【解决方案2】:

    去掉不需要的动态关键字即可回答原问题:

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ output extension=".cs" #>
    <#
        var enum_values = new /* OMIT dynamic */ [] {
            new { EnumName = "HoverDatePicker.Mode", Value = "View"},
            new { EnumName = "HoverDatePicker.Mode", Value = "Mode"},
            new { EnumName = "Frequency", Value = "Monthly"},
            new { EnumName = "Frequency", Value = "Weekly"}
        };
    #>
    <#
    for(int i = 0; i < enum_values.Length; i++)
    { #>
        public class <#= enum_values[i].Value #>VisibilityConverter : IValueConverter
        {
        }
    <# 
    } #>
    

    【讨论】:

      猜你喜欢
      • 2011-07-03
      • 2013-04-26
      • 2013-09-18
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多