使用带有T4模板的匿名类型进行类生成

时间:2016-09-05 09:53:42

标签: c#-4.0 t4 anonymous-types

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

这是一个最小的片段,目的是说明我的使用模式,这也是我遇到的问题的例子:

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类生成器的匿名类型,那将是非常有帮助的。所以提前谢谢大家!

2 个答案:

答案 0 :(得分:0)

我最终通过明确指定来完成这项工作,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
    {
    }
<# 
} #>

答案 1 :(得分:0)

原始问题可以通过删除不需要的动态关键字来解决:

<#@ 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
    {
    }
<# 
} #>