我把一个相当复杂的东西塞进了T4模板。基本上我采取像
这样的东西{= foo =}更多文字......
并将其转换为类(视图),如下所示:
public class MyView
{
public string foo{get;set;}
public string Write()
{
return foo+@" more text...";
}
}
生成的代码当然比这复杂得多。无论如何,T4模板现在超过600行代码,并且真正变得难以管理。我认为主要的问题是混合代码和内容"(即静态代码)。我不确定如何干净地解决这个问题(当然不会影响生成的代码)。我也没有看到任何可行的单元测试我的T4代码的方法,除了简单地测试它的T4执行错误。当然,似乎几乎不可能测试它生成的代码。
是否有"模型视图"类型框架或技术我可以用来使我的T4模板代码更干净?
答案 0 :(得分:5)
恕我直言,编写复杂模板时最重要的两个概念是
不那么重要但很好
分离模型/视图的示例:
<#
// Model for Dependency Pooperties
Model = new []
{
new ClassDefinition ("MyDataGrid")
{
P ("CultureInfo" , "CultureInfo"),
P ("Pen" , "CellBorderPen"),
P ("IEnumerable<object>" , "Rows"),
C ("WColumnDefinition" , "Columns"),
},
};
#>
// Include the view
<#@ include file="..\T4\DependencyProperties.ttinclude" #>
然后,视图遍历模型并生成依赖项属性。
然后,依赖项属性的行为将作为部分方法实现
partial void Changed_Columns(
ObservableCollection<WColumnDefinition> oldValue,
ObservableCollection<WColumnDefinition> newValue
)
{
HookUpColumns(oldValue, null);
HookUpColumns(newValue, this);
}
请注意,将此特定行为放入模型会使模型复杂化。
最后;即使是一个称职的程序员也需要时间才能胜任地编写元程序。在我找到一种我认为可维护的风格之前,我花了好几次尝试,但对我而言,我能够更快地提供质量,这是值得的。
我希望这会有所帮助......
PS。我不认为有人会认为T4是优雅的,但它仍然很有用。
答案 1 :(得分:1)
经过漫长的旅程,我终于在第一次单元测试中检查了我的T4模板。基本上,我所做的是抽象出一个“视图”(实际的T4模板)和“逻辑”(生成代码,但实际上不输出它而不依赖于T4)
然后我更进了一步并使用了一个大的hack来使我的逻辑文件在T4之外编译。这具有很好的效果,使智能感知和编译器错误起作用。它还允许我通过简单地引用项目从单元测试中访问我的逻辑类。
我写了一篇完整的代码示例(之前/之后)和示例单元测试on my blog的文章,如果你想了解如何做的冗长细节。