在运行时创建T4模板(编译时)?模板

2023-09-02 01:54:43 作者:无上限宠你

我们正在构建一个需要生成HTML文件上传到易趣物品的室内应用。我们正在使用模板引擎,以产生基于我们有$ P $对 - 定义数据库和静态字段HTML文件。该模板还需要具有逻辑能力(如果 - 则,的foreach等)。

We are building an inhouse application which needs to generate HTML files for upload into eBay listings. We are looking to use a template engine to generate the HTML files based on database and static fields that we have pre-defined. The template also needs to have logic capabilities (if-then, foreach, etc).

我们已经看了T4,它看起来完美的,但我们没有看到关于它是否在运行时使用的任何功能,使用户可以创建T4模板,然后应用程序可以编译它并生成最终的HTML文件。这是可能的,如何?

We have looked at T4 and it looks perfect, but we don't see anything about whether it has the capabilities to be used at runtime, so that a user can create the T4 template, and then the application can "compile" it and generate the final HTML file. Is this possible, and how?

如果不是,我们应该看还有其他框架拥有所有这些功能?

If not, are there other frameworks we should be looking at that has all these capabilities?

推荐答案

我有一个类似的一套,我使用的这个班,模板嵌入文本生成到软件。

I have a similar set of classes that I use for this, embedding templated text generation into software.

基本上,它就像旧式的ASP,您围绕C#code。在<%......%> 块,你可以发射结果通过使用<%= EX pression%GT;

Basically, it works like old-style ASP, you surround C# code in <%...%> blocks, and you can emit results by using <%= expression %>.

您可以通过一个单一的对象到模板中code,这当然可以是任何你喜欢的对象类型,或者参数只是一个数组。您也可以参考自己的组件,如果你想执行自定义code。

You can pass a single object into the template code, which of course can be any object type you like, or simply an array of parameters. You can also reference your own assemblies if you want to execute custom code.

下面是如何发光类会是什么样:

Here's how emitting a class would look:

<%
var parameters = (string[])data;
var namespaceName = parameters[0];
var className = parameters[1];
%>
namespace <%= namespaceName %>
{
    public class <%= className %>
    {
    }
}

您可以通过东西当然循环:

You can of course loop through things:

<% foreach (var parameter in parameters) { %>
<%= parameter %>
<% } %>

和放code中,如果块等。

and put code in if-blocks etc.

该类库释放codePLEX这里:

The class library is released on CodePlex here:

codePLEX:TextTemplate

以及对的NuGet 。

该项目附带的例子,下载源或浏览它的在线。

The project comes with examples, download the source or browse it online.

要回答电子邮件的问题也在这里,给别人看的:

To answer questions by email also here, for others to see:

在所有类型的C#code的的适合方法调用的,可在模板中进行编译。它运行正常的C#3.5 code,用一切手段,有没有人为的限制。唯一的事情知道的是,如果任何,而对于,的foreach等code包含模板code发出必须使用大括号,你不能做一个单行的if-then型块。见下面的方法调用的限制。 的数据参数对应的任何传入从参数到 .Generate(X)方法你的应用程序,并且是同一类型。如果你传递你已经在你自己的类库定义的对象,你需要添加一个参考模板code,以便正确地访问它。 (&LT;%@参考your.class.library.dll%&GT; ) 如果您重用已编译的模板,它在本质上只是一个方法调用的一类,没有额外的开销进行实际调用 .Generate() 。如果你不叫 .Compile()自己,到第一个呼叫 .Generate()会照顾它。另请注意,code在一个单独的AppDomain中运行,所以这是一个轻微的编组开销与复制参数和结果来回。在code,然而,在运行正常的即时编译.NET code的速度。 All types of C# code that fit into a method call can be compiled in the template. It runs normal C# 3.5 code, with everything that means, there's no artificial limits. Only things to know is that any if, while, for, foreach, etc. code that contains template code to emit must use braces, you cannot do a single-line if-then type block. See below for the method-call limitation. The data parameter corresponds to whatever was passed in as the parameter to the .Generate(x) method from your application, and is of the same type. If you pass in an object you have defined in your own class libraries, you need to add a reference to the template code in order to properly access it. (<%@ reference your.class.library.dll %>) If you reuse the compiled template, it will in essence only be a method call to a class, no additional overhead is done on the actual call to .Generate(). If you don't call .Compile() yourself, the first call to .Generate() will take care of it. Also note that the code runs in a separate appdomain, so there's a slight marshalling overhead related to copying the parameter and result back and forth. The code, however, runs at normal JITted .NET code speed.

如果块的例子:

<% if (a == b) { %>
This will only be output if a==b.
<% } %>

有一个关于格式化code没有人为限制或者,挑选最适合您的风格:

There's no artificial limits on formatting the code either, pick the style that suits you best:

<%
    if (a == b)
    {
%>
This will only be output if a==b.
<%
    }
%>

只有注意,模板的所有非code部位将pretty的多是原样输出,这意味着标签和这样的下面%&GT; 块将输出为好。

有一个限制,所有的code编写必须适合单个方法调用中。

There is one limit, all the code you write must fit inside a single method call.

让我来解释一下。

模板引擎的工作方式是,它会产生一个cs文件,将其提供给C#编译器,这.cs文件roughyly看起来是这样的:

The way the template engine works is that it produces a .cs file and feeds it to the C# compiler, this .cs file roughyly looks like this:

using directives

namespace SomeNamespace
{
    public class SomeClass
    {
        public string Render(object data)
        {
            ... all your code goes here
        }
    }
}

这意味着你不能定义新的类,新的方法,类级别的领域,等等。

This means that you cannot define new classes, new methods, class-level fields, etc.

您可以,但是,使用匿名委托在内部创建函数。举例来说,如果你想要的格式日期以统一的方式:

You can, however, use anonymous delegates to create functions internally. For instance, if you want a uniform way of formatting dates:

Func<DateTime, string> date2str = delegate(DateTime dt)
{
    return dt.ToString("G");
};

那么你可以简单地使用在模板code休息:

then you can simply use that in the rest of the template code:

<%= date2str(DateTime.Now) %>

只是要求我必须是你不上传文件到网站,并声称你写的code,比你可以自由地做你想做的事情等。

Only requirement I have is that you don't upload the files onto the web and claim you wrote the code, other than that you're free to do what you want with it.

修改2011年4月23日:固定链接至codePLEX项目

Edit 23.04.2011: Fixed links to CodePlex project.