说到代码生成,大家可能都会想到 T4,可惜的是 T4 需要预编译。
那么就先来看看 t4 如何运行时获得结果的代码:
首先添加一个 HelloWorld.tt 内容如下:
<#@ template debug="false" hostspecific="false" language="C#" #> <#@ parameter name="name" type="System.String" #> Hello <#= name#> Welcome to t4!修改 tt 的 Customer Tool 属性:TextTemplatingFileGenerator 改为 TextTemplatingFilePreprocessor 保存之后,会自动生成一个 HelloWorld.cs 文件。
HelloWorld t4Template = new HelloWorld(); t4Template.Session = new Dictionary<string, object> { { "name", "World" } }; t4Template.Initialize(); string result = t4Template.TransformText();不难看出,T4 的模板需要预编译,生成模板的静态类型再动态传入值生成结果。 所以难以达到动态添加,修改模板的要求。
string template = "Hello @Model.Name! Welcome to Razor!"; string result = Razor.Parse(template, new { Name = "World" });没有预编译,只需要动态的传值,字符串即模板。这就给模板的变化带来极大的想象空间,比如:在线的模板修改保存,提供数据并生成结果。
输出的效果
这样任何项目,只要随时定义模板就可即时获得结果,也不要编译。
其实实现也很简单:输入的全局数据和多行数据(第一行数据作为 dynamic 对象的属性)解析后填充到 ExpandoObject 里交给 Razor 就可以了~
private List<dynamic> ParseListData(string content, char[] separator) { var datas = new List<dynamic>(); var lines = content.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries); if (lines.Length <= 0) return datas; string[] columns = null; int index = 0; foreach (var line in lines) { var handledline = line; if (separator.Any(c => c == ' ')) { handledline = Regex.Replace(line, "\\s+", " "); } if (index == 0) { columns = handledline.Split(separator, StringSplitOptions.RemoveEmptyEntries); columns = columns.Select(col => col.Trim()).ToArray(); } else { var fieldValues = handledline.Split(separator); dynamic obj = new ExpandoObject(); var dict = (IDictionary<string, object>)obj; for (int i = 0; i < fieldValues.Length; i++) { dict[columns[i].Trim()] = fieldValues[i].Trim(); } datas.Add(obj); } index++; } return datas; }