【问题标题】:How to generate a simple class with T4?如何用 T4 生成一个简单的类?
【发布时间】:2017-07-10 06:17:21
【问题描述】:

我正在开发一个 VSPackage,它应该从数据库中的一些数据生成简单的类。我已经有一个静态方法GetFieldInfo 从数据库中获取我需要的数据,GetFieldInfo 返回一个List<TableField>,其中TableField 是一个自定义类,它包含我需要的所有数据。

到目前为止,我的 T4 模板如下所示:

<#@ template language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Threading.Tasks" #>
<#@ output extension=".cs" #>
<#@ parameter name="namespace" type="System.String" #>
<#@ parameter name="className" type="System.String" #>
<#@ parameter name="fields" type="System.Collections.Generic.List<TableField>" #>

namespace <#= this.namespace #>
{
    public class <#= classname #>
    {
        <#
            foreach (TableField campo in fields)
            {

            }
        #>
    }
}

所有这些(静态方法、自定义类和模板)都在同一个项目的不同命名空间中。这个项目(我们称它为“辅助项目”)不是 VSPackage 项目(它是在 VSPackage 一中作为参考添加的)。

我的问题是,这个模板吐出了 27 个难以理解的错误(例如:Class, delegate, enum, interface or struct expected 在第 2 行第 9 列;} expected 在第 7 行第 9 列;method must have a return value 在第 15 行第 18 列)坦率地说,我什至不知道从哪里开始检查。当有许多奇怪的错误时,我的直觉告诉我,通常是因为开发人员忘记添加/配置一些简单的事情,但到目前为止我还没有找到任何可以帮助我的东西。在 Google 中,我没有找到通过 T4 生成类的教程/示例。

我想生成什么?这个:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace [TARGET_PROJECT_NAMESPACE]
{
    public class [TABLE_NAME]
    {
        public [FIELD_TYPE] [FIELD_NAME] { get; set; }
    }
}

那么,我做错了什么?

【问题讨论】:

  • 您在模板中使用参数。你将如何将它们传递给模板?
  • @evk 我还没有找到方法。我知道VS provides a templating host我也许可以使用。
  • 这意味着您不需要在设计时生成任何输出。产生这些错误是因为 VS 试图在设计时转换您的模板,但这没有任何意义。所以右键单击您的模板,转到属性并删除“自定义工具”。请注意,您的模板仍然可能是错误的(例如,您使用没有命名空间的 TableField),但这是另一回事。
  • ...问题来了:也许我应该放弃 T4 并使用旧的 CodeDOM?我最担心的是我的 VSPackage 可以毫无问题地将我生成的类添加到目标项目中。
  • 我没有在 VS 插件中使用 T4 模板的经验。我通常使用它们通过反射检查一些代码并在 design time 中生成另一个代码(所以没有参数)。在这种情况下(设计时生成)它非常有用。在任何其他情况下......怀疑。所以我会说使用任何对你来说更方便的东西。如果您决定仍然使用 T4 模板 - 至少安装 VS 插件,它在那里提供语法突出显示。

标签: c# templates code-generation t4


【解决方案1】:

抱歉,无法添加评论 - 仍然没有“50 声望”。

首先 - 您需要参考定义 TableField 和您在模板中使用的其他部分的命名空间。添加 。

第二 - 您希望在生成的代码中有很多“使用”语句 - 您需要将它们作为文本放入模板中。

关于 VSPackage - 请记住,您有两个阶段 - 模板编译和代码生成,并且有两个自定义工具可以在第一阶段或两个阶段完成。很可能您需要在开发阶段进行模板编译,并在使用包时执行模板。

提示:如果模板没有做它应该做的事情 - 将模板简化为基本模板 - 让他一次又一次地生成相同的静态代码。

【讨论】:

    【解决方案2】:

    右键单击您的.tt 文件并确保您的Custom Tool 的值设置为TextTemplatingFilePreProcessor

    创建新模板时的样板代码应该为您生成一个类 - 例如,如果您将模板命名为 StackOverflowTemplate.tt,那么您也应该有一个名为 StackOverflowTemplate 的类。

    您可以实例化 StackOverflowTemplate 类以将参数添加到模板中,如下所示:

    Program.cs

    public class Program
    {
        static void Main(string[] args)
        {
            List<TableField> fields = new List<TableField>();
    
            StackOverflowTemplate sft = new StackOverflowTemplate();
            sft.Session = new Dictionary<string, object>();
            sft.Session.Add("_namespace", "TargetProjectNamespace");
            sft.Session.Add("className", "ClassName");
            sft.Session.Add("fields", fields);
            sft.Initialize();
            string output = sft.TransformText();
            Console.WriteLine(output);
            Console.ReadKey();
        }
    }
    

    StackOverflowTemplate.tt

    <#@ template language="C#" #>
    <#@ parameter name="_namespace" type="System.String" #>
    <#@ parameter name="className" type="System.String" #>
    <#@ parameter name="fields" type="System.Collections.Generic.List<TableField>" #>
    namespace <#= _namespace #>
    {
        public class <#= className #>
        {
            <#
                foreach (TableField campo in fields)
                {
    
                }
            #>
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-26
      • 2010-11-22
      • 2012-02-16
      • 2013-09-18
      • 2011-06-12
      • 2011-03-01
      • 1970-01-01
      相关资源
      最近更新 更多