将对象传递给T4模板

时间:2011-05-31 18:48:29

标签: c# .net templates t4

我有u1类的对象User。用户具有属性name。如何将u1传递给T4模板?我想做一些非常简单的事情:

User u1 = new User("John"); 


模板脚本:

Hello <# u1.Name #>

5 个答案:

答案 0 :(得分:3)

我们做了类似的事情。我们的解决方案包含以下要素:

  • 自定义主机
  • 自定义模板基类(模板指令的“inherits”属性)
  • 主机特定模板(模板指令的“hostspecific”属性)

自定义主机由模板本身想要调用方法的对象聚合。

interface ICallbackInterface
{
    void CallbackFxn();
}

[Serializable]
public class MyCustomHost : ITextTemplatingEngineHost, ITextTemplatingSessionHost, IStencilFileRecordManagement
{

    private ICallbackInterface callback = null;
    public MyCustomHost(ICallbackInterface cb)
    {
        callback = cb;
    }

    public void CallbackFxn()
    {
        callback.CallbackFxn();
    }
}

public abstract class MyTemplateBase : TextTransformation
{
    public virtual MyCustomHost CustomHost
    {
        get
        {
            dynamic metame = this;
            MyCustomHost rval = null;
            try
            {
                /// <summary>
                /// The "Host" property will be added to the generated class by the T4 environment whenever a 
                /// "hostspecific" template is processed. 
                /// </summary>
                rval = metame.Host as MyCustomHost;
            }
            catch (RuntimeBinderException e)
            {
                logger.ErrorException(
                    "Received the following exception while processing a stencil template", e);

            }
            return rval;
        }
    }
}

现在,在我们的任何模板中,我们可以使用自定义主机属性调用实际启动处理的对象上的方法,例如:

<# CustomHost.CallbackFxn(); #>

此外,我们不在VS中使用T4或使用单独的可执行文件 - 我们链接Microsoft.VisualStudio.TextTemplating.10.0和Microsoft.VisualStudio.TextTemplating.Interfaces.10.0程序集。

修改

我们正在使用T4模板,允许用户定义自己的插件,以便在我们的产品工作流程的特定步骤中使用。因此,用户模板会上传到我们的系统,并按照以下方式进行处理:

using Microsoft.VisualStudio.TextTemplating;

class UserPluginWorkflowComponent : ICallbackInterface
{
    public void CallbackFxn()
    {
        // invoked by user plugin
    }

    public void ExecuteUserPlugin()
    {
        MyCustomHost host = new MyCustomHost(this);
        host.TemplateFileValue = "UserPluginTemplateFilename";
        Engine engine = new Engine();
        string pluginResult = engine.ProcessTemplate(
            userPluginTemplateFileContents, 
            host);            
        if (!host.Errors.HasErrors)
        {
            // use pluginResult in some meaningful way
        }
    }
}

答案 1 :(得分:2)

你想在你的模板中使用它吗?然后,您需要添加对包含该类型的程序集的引用。你不能简单地将现有的引用传递给T4引擎,除非你以一种非常不正统的方式自己托管(我从来没有见过有人试图这样做)。即使你走得那么远,你会怎么运行呢?这个引用应该来自哪里?

使用T4模板中的类型就像添加引用或将其复制/粘贴到类存根<#+ /*stuff goes here*/ #>一样简单。

答案 2 :(得分:1)

T4模板在一个步骤中处理,因此模板需要在其运行期间获得所需的一切,因为您并没有真正“通过”任何内容。由于模板是文本,我通常只有一些开发人员可以在文件顶部设置的参数。如果你需要用户输入,你可以弹出一个窗口,但是在生成代码时听起来很烦人。

另一个解决方案是使用在t4模板中使用模板替换的自定义模板,类似于许多已安装模板的工作方式。

答案 3 :(得分:1)

假设您希望在最终运行模板的某些应用程序或工具中包含代码,则使用运行时(预处理)模板,其中包含在&lt;#+#&gt;中定义的自定义属性。类功能块或&lt;#@ parameter#&gt;指令应该给你你想要的东西。

在这里查看文档:{​​{3}}

答案 4 :(得分:0)

嘿 - 您需要在T4脚本中设置值等,因此User初始化必须在<# #>标记内进行,这会使您的示例变为类似于

的内容
     <# User u1 = new User() { .Name = "John" } #>
     Hello <# u1.Name #> 

如上所述,您可能还需要导入名称空间。我在TT文件的开头使用了以下语句来访问System.Data:

     <#@ import namespace="System.Data" #>
     <#@ import namespace="System.Data.SqlClient" #>
     <#@ assembly name="System.Data" #>