1、引入RazorEngine组件
2、编写模板管理类TemplateManager.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using RazorEngine; using RazorEngine.Configuration; using RazorEngine.Templating; namespace GhisCodeGenerator.Comm { /// <summary> /// 模板管理器 /// </summary> public static class TemplateManager { public static string TemplateRootPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Tpls"); public static Dictionary<string, string> TemplateDic = new Dictionary<string, string>(); public static void Init() { //生成tpl文件 //CsHtmlToTpl(); var templateServiceConfiguration = new TemplateServiceConfiguration(); //这里可以类引用解决器 templateServiceConfiguration.ReferenceResolver = new CustomReferenceResolver(); Engine.Razor = RazorEngineService.Create(templateServiceConfiguration); } /// <summary> /// Cses the HTML to TPL. /// </summary> private static void CsHtmlToTpl() { var root = new DirectoryInfo(TemplateRootPath); var fileInfos = root.GetFiles("*.cshtml").ToList(); foreach (var directory in root.GetDirectories()) { fileInfos.AddRange(directory.GetFiles("*.cshtml")); } fileInfos.ForEach(x => { File.Copy(x.FullName, x.FullName.Replace(".cshtml", ".tpl"), true); }); } /// <summary> /// Creates the directory and remove file. /// </summary> /// <param name="filepath">The filepath.</param> public static void CreateDirectoryAndRemoveFile(string filepath) { var dir = Path.GetDirectoryName(filepath); if (!Directory.Exists(dir)) { Directory.CreateDirectory(dir); } if (File.Exists(filepath)) { File.Delete(filepath); } } /// <summary> /// 获取所有模板 /// </summary> public static List<string> GetTpls() { var root = new DirectoryInfo(TemplateRootPath); var fileInfos = root.GetFiles("*.cshtml").ToList(); foreach (var directory in root.GetDirectories()) { fileInfos.AddRange(directory.GetFiles("*.cshtml")); } List<string> tpls = new List<string>(); foreach (FileInfo fileInfo in fileInfos) { tpls.Add(fileInfo.FullName.Replace(TemplateRootPath, "").TrimStart('\\')); } return tpls; } /// <summary> /// Loads the templates. /// </summary> /// <param name="clearCache">if set to <c>true</c> [clear cache].</param> public static void LoadTemplates(bool clearCache = false) { if (clearCache) { TemplateDic.Clear(); } LoadTemplates(new DirectoryInfo(TemplateRootPath)); } /// <summary> /// Loads the templates. /// </summary> /// <param name="directoryInfo">The directory information.</param> private static void LoadTemplates(DirectoryInfo directoryInfo) { if (!directoryInfo.Exists) { return; } var fileInfos = directoryInfo.GetFiles("*.cshtml"); foreach (var fileInfo in fileInfos) { LoadTemplate(fileInfo.FullName.Replace(TemplateRootPath, "")); } foreach (var directory in directoryInfo.GetDirectories()) { LoadTemplates(directory); } } /// <summary> /// 加载模板 /// </summary> /// <param name="relativePath">The relative path.</param> public static void LoadTemplate(string relativePath) { relativePath = relativePath.TrimStart('\\'); //打开并且读取模板 string template = File.ReadAllText(Path.Combine(TemplateRootPath, relativePath)); //添加模板 Engine.Razor.AddTemplate(relativePath, template); //编译模板 Engine.Razor.Compile(relativePath, null); if (!TemplateDic.ContainsKey(relativePath)) { TemplateDic.Add(relativePath, ""); } else { TemplateDic[relativePath] = ""; } } /// <summary> /// 运行模板 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="templatePath">The template path.</param> /// <param name="model">The model.</param> /// <returns></returns> public static string Run<T>(string templatePath, T model) { return Engine.Razor.Run(templatePath, null, model); } public static string Run<T>(int idx, T model) { return Engine.Razor.Run(TemplateDic.Keys.ToList()[idx], null, model); } } }
编写CustomReferenceResolver.cs
using System.Collections.Generic; using System.IO; using System.Linq; using RazorEngine.Compilation; using RazorEngine.Compilation.ReferenceResolver; namespace GhisCodeGenerator.Comm { public class CustomReferenceResolver : IReferenceResolver { /// <summary> /// <see cref="CompilerServiceBase.DynamicTemplateNamespace"/> /// </summary> protected internal const string DynamicTemplateNamespace = "CompiledRazorTemplates.Dynamic"; /// <summary> /// See <see cref="IReferenceResolver.GetReferences"/> /// </summary> /// <param name="context"></param> /// <param name="includeAssemblies"></param> /// <returns></returns> public IEnumerable<CompilerReference> GetReferences(TypeContext context = null, IEnumerable<CompilerReference> includeAssemblies = null) { return CompilerServicesUtility .GetLoadedAssemblies() .Where(a => !a.IsDynamic && File.Exists(a.Location) && !a.Location.Contains(DynamicTemplateNamespace)) .GroupBy(a => a.GetName().Name).Select(grp => grp.First(y => y.GetName().Version == grp.Max(x => x.GetName().Version))) // only select distinct assemblies based on FullName to avoid loading duplicate assemblies .Select(a => CompilerReference.From(a)) .Concat(includeAssemblies ?? Enumerable.Empty<CompilerReference>()); } } }
3、准备模板文件demo.cshtml
文件为什么是cshtml?因为我想让我编写模板的时候,能语法高亮,能有智能提示,能和mvc开发绑定数据一样去开发
注意:需要将我们的模板文件(.cshtml)属性调整为内容,阻止编译,我们要像使用txt一样去使用他们
4、模板是否正确,是否能编译通过,需要我们初始化,不然后期生成代码的时候,会非常慢
所以需要在程序启动时候去初始化
using System; using System.Windows.Forms; using GhisCodeGenerator.Comm; namespace GhisCodeGenerator { static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main() { TemplateManager.Init();//这里 Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Frm_Main()); } } }
这样做,会导致我们的程序启动的时候,稍微慢了一点点,但是为了后期使用非常流畅,还是值得
到这里,我们的准备工作已经完成,接下来就是运用了
5、运用,即点击生成代码按钮之后该干的事情
List<string> tpls = TemplateManager.GetTpls();//得到所有模板 for (var i = 0; i < tpls.Count; i++) { //一次处理所有模板 var codeStr = TemplateManager.Run(tpls[i], ClassInfo);//将模板和razor绑定的数据传过去,这个classInfo就是渲染数据 var path = Path.Combine(savepath, ClassInfo.OutPutFileName);//根据回写的地址输出文件,这里决定了输出文件位置和后缀名 TemplateManager.CreateDirectoryAndRemoveFile(path);//创建文件夹 using (var stream = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write)) //写入文件 { using (var writer = new StreamWriter(stream, Encoding.UTF8)) { writer.Write(codeStr); } } }
模板一般都是很多个,而且生成的代码需要存放在不同的文件夹,文件名称和后缀也不一样,所以我们把FileName放在模板中来赋值
最后生成的文件输出的位置和后缀名,完全取决于模板文件中的OutPutFileName变量
留下您的脚步
最近评论