我们正在构建一个内部应用程序,它需要生成 HTML 文件以上传到 eBay 列表中。我们希望使用模板引擎根据我们预定义的数据库和静态字段生成 HTML 文件。该模板还需要具有逻辑功能(if-then、foreach 等)。
我们看过 T4,它看起来很完美,但我们没有看到任何关于它是否具有在运行时使用的能力,以便用户可以创建 T4 模板,然后应用程序可以“编译”它并生成最终的 HTML 文件。这可能吗?如何实现?
如果没有,我们是否应该考虑其他具有所有这些功能的框架?
最佳答案
我有一组类似的类用于此,将模板化文本生成嵌入到软件中。
基本上,它像旧式 ASP 一样工作,您将 C# 代码包围在 <%...%>
中 block ,您可以使用 <%= expression %>
发出结果.
您可以将单个对象传递到模板代码中,当然可以是您喜欢的任何对象类型,或者只是一个参数数组。如果要执行自定义代码,也可以引用自己的程序集。
下面是发出一个类的样子:
<%
var parameters = (string[])data;
var namespaceName = parameters[0];
var className = parameters[1];
%>
namespace <%= namespaceName %>
{
public class <%= className %>
{
}
}
你当然可以遍历事物:
<% foreach (var parameter in parameters) { %>
<%= parameter %>
<% } %>
并将代码放入 if block 等
类库在此处的 CodePlex 上发布:
以及 NuGet .
项目自带例子,下载源码或browse it online .
也在这里通过电子邮件回答问题,以供其他人查看:
- 所有类型的 C# 代码适合方法调用 都可以在模板中编译。它运行正常的 C# 3.5 代码,这意味着没有人为限制。唯一要知道的是,任何包含要发出的模板代码的 if、while、for、foreach 等代码都必须使用大括号,不能使用单行 if-then 类型 block 。请参阅下文了解方法调用限制。
data
参数对应于作为参数传递给.Generate(x)
的任何内容来自您的应用程序的方法,并且属于同一类型。如果你传入一个你在自己的类库中定义的对象,你需要添加对模板代码的引用才能正确访问它。 (<%@ reference your.class.library.dll %>
)- 如果您重用已编译的模板,它本质上只是对类的方法调用,对
.Generate()
的实际调用不会产生额外的开销。 .如果你不打电话.Compile()
你自己,第一个电话.Generate()
会处理的。另请注意,代码在单独的应用程序域中运行,因此与来回复制参数和结果相关的编码开销很小。但是,代码以正常的 JITted .NET 代码速度运行。
if block 的例子:
<% if (a == b) { %>
This will only be output if a==b.
<% } %>
代码格式也没有人为限制,选择最适合您的样式:
<%
if (a == b)
{
%>
This will only be output if a==b.
<%
}
%>
请注意,模板的所有非代码部分几乎都将按原样输出,这意味着制表符和 %>
之后的类似内容 block 也将被输出。
有一个限制,您编写的所有代码都必须放在一个方法调用中。
让我解释一下。
模板引擎的工作方式是生成一个 .cs 文件并将其提供给 C# 编译器,这个 .cs 文件大致如下所示:
using directives
namespace SomeNamespace
{
public class SomeClass
{
public string Render(object data)
{
... all your code goes here
}
}
}
这意味着您不能定义新类、新方法、类级字段等。
但是,您可以使用匿名委托(delegate)在内部创建函数。例如,如果您想要一种统一的格式日期方式:
Func<DateTime, string> date2str = delegate(DateTime dt)
{
return dt.ToString("G");
};
然后您可以在其余的模板代码中简单地使用它:
<%= date2str(DateTime.Now) %>
我唯一的要求是您不要将文件上传到网络上并声称您编写了代码,除此之外您可以自由地使用它做任何您想做的事情。
编辑 23.04.2011:修复了指向 CodePlex 项目的链接。
关于c# - 在运行时(构建时)创建 T4 模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2307567/