自定义 T4 预处理模板

本文关键字:预处理 T4 自定义 | 更新日期: 2023-09-27 18:35:09

我想做什么

我正在尝试使用 T4 创建邮件模板。

正在使用一个预处理的模板,如果我理解正确,如果我想在运行时生成消息而不引入对Microsoft.VisualStudio.TextTemplating程序集的依赖,这就是我必须做的。

由于我想将一些数据传递给我的模板,因此我向其添加了参数:

<#@ template language="C#" #>
<#@ parameter name="Param1" type="System.String" #>
<#@ parameter name="Param2" type="System.    
Lorem <#= Param1 #> dolor <#= Param2 #>

然后我可以生成传递参数的消息,如下所示:

static void Main(string[] args) {
    var template = new LoremIpsum();
    template.Session = new Dictionary<string, object>() { 
        {"Param1", "ipsum"},
        {"Param2", "sit amet"},
    };
    template.Initialize();
    string text = template.TransformText();
}

问题出在哪里

由于我需要生成其中的几个类,我希望它们都有一个通用的方法来发送邮件,如下所示:

public void SendMail(string to, IDictionary<string, object> parameters)

或者,甚至更好:

public void SendMail(string to, string Param1, string Param2)
由于生成的类是分部

的,因此可以向它们添加方法,添加另一个分部类声明,但这意味着我必须为所有生成的类重复(或多或少)相同的代码。

到目前为止我尝试过什么

我尝试创建一个基类,但如果我尝试这样做:

<#@ template language="C#" inherits="MailTemplateBase" #>

然后生成的代码中断,因为生成的类依赖于定义一些帮助程序方法的LoremIpsumBase基类(我真的认为让每个生成的类从几乎相同但不同的基类继承没有意义)。

问题

  1. 如何为我的模板设置基类?
  2. 如何生成接受与模板中声明的参数相同的参数的方法?

自定义 T4 预处理模板

我认为您需要创建一个空模板,复制创建的类并将其用作基类。然后,您可以使用所需的任何属性对其进行扩展。(复制代码后,无需保留空模板)

对于它的价值,我认为您正在尝试做的事情在VS 2010 RTM中开箱即用,但是VS2010 SP1改变了行为,因此您可以自己对模板进行子类。有关详细信息,请查看此连接问题。

编辑:

就将电子邮件方法放在底座上而言,我可能不会那样做。您可能需要考虑公开某种模板服务,该服务具有您需要的各种方法,例如:

public class TemplatingService : ITemplatingService
{
    public string GenerateReminderMessage(string to, string name)
    {
        // Construct the template, passing in the parameters into the session as required
        ...
        // Return the results of the template transformation
    }
}

这样,您将从实际的 T4 实现中抽象出来,因此,如果某些内容确实在某个地方发生故障,您只需在一个类中修复它。

并公开使用模板服务生成邮件内容的邮件服务:

public class MailService : IMailService
{
    public void SendReminderEmail(string to, string name)
    {
        var message = this.TemplatingService.GenerateReminderMessage(to, name);
        this.MailerService.SendEmail(to, message);
    }
}

请注意,MailerService 只是 .NET 邮件代码的简单包装器,但它允许您单独对 MailService 进行单元测试。

可能有更多的方法可以抽象出来,但这将是一个开始。

希望有帮助。

听起来你假设构造函数注入是将数据注入类的唯一方法。但是,我想在这种情况下,梅托德/属性注入是更好的选择。

我手头没有编译器,也无法确定验证它,但似乎它可以工作。