首页 > 编程 > C# > 正文

C#如何通过T4自动生成代码详解

2019-10-29 19:58:28
字体:
来源:转载
供稿:网友

T4简介

T4(Text Template Transformation Toolkit)在 Visual Studio 中,“T4 文本模板”是由一些文本块和控制逻辑组成的混合模板,它可以生成文本文件。 在 Visual C# 或 Visual Basic 中,控制逻辑编写为程序代码的片段。生成的文件可以是任何类型的文本,例如网页、资源文件或任何语言的程序源代码。

T4 文本模板有两种类型:

1、运行时模板

可在应用程序中执行运行时 T4 文本模板(“预处理过的”模板)以便生成文本字符串(通常作为其输出的一部分)。

若要创建运行时模板,请向您的项目中添加“已预处理的文本模板”文件。

另外,您还可以添加纯文本文件并将其“自定义工具”属性设置为“TextTemplatingFilePreprocessor”。

2、设计时模板

在 Visual Studio 中执行设计时 T4 文本模板,以便定义应用程序的部分源代码和其他资源。

通常,您可以使用读取单个输入文件或数据库中的数据的多个模板,并生成一些 .cs、.vb 或其他源文件。

每个模板都生成一个文件。 在 Visual Studio 或 MSBuild 内执行它们。

若要创建设计时模板,请向您的项目中添加“文本模板”文件。 另外,您还可以添加纯文本文件并将其“自定义工具”属性设置为“TextTemplatingFileGenerator”。

通过T4模板生成代码,运行时实现

关键代码段:Host

using Microsoft.VisualStudio.TextTemplating;using System;using System.CodeDom.Compiler;using System.Collections.Generic;using System.IO;using System.Linq;using System.Text;using System.Threading.Tasks;namespace CodeGenerate.EngineHost{ public class TextTemplatingEngineHost : ITextTemplatingEngineHost, ITextTemplatingSessionHost { public List<string> LocalDlls { get; set; } public List<string> Namespaces { get; set; } /// <summary> /// 模板文件 /// </summary> public string TemplateFile { get; set; } /// <summary> /// 文件扩展名 /// </summary> public string FileExtension { get; set; } /// <summary> /// 文件扩展名 /// </summary> public Encoding FileEncoding { get; set; } /// <summary> /// 错误信息 /// </summary> public CompilerErrorCollection Errors { get; set; } public IList<string> StandardAssemblyReferences {  get  {  LocalDlls.Add(typeof(System.Uri).Assembly.Location);  return LocalDlls;  } } public IList<string> StandardImports {  get  {  Namespaces.Add("System");  return Namespaces;  } } /// <summary> /// 参数传递 /// </summary> public ITextTemplatingSession Session { get; set; } public bool LoadIncludeText(string requestFileName, out string content, out string location) {  content = System.String.Empty;  location = System.String.Empty;  if (File.Exists(requestFileName))  {  content = File.ReadAllText(requestFileName);  return true;  }  else  {  return false;  } } public object GetHostOption(string optionName) {  object returnObject;  switch (optionName)  {  case "CacheAssemblies":   returnObject = true;   break;  default:   returnObject = null;   break;  }  return returnObject; } public string ResolveAssemblyReference(string assemblyReference) {  if (File.Exists(assemblyReference))  {  return assemblyReference;  }  string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), assemblyReference);  if (File.Exists(candidate))  {  return candidate;  }  return ""; } public Type ResolveDirectiveProcessor(string processorName) {  if (string.Compare(processorName, "XYZ", StringComparison.OrdinalIgnoreCase) == 0)  {  //return typeof();   }  throw new Exception("Directive Processor not found"); } public string ResolvePath(string fileName) {  if (fileName == null)  {  throw new ArgumentNullException("the file name cannot be null");  }  if (File.Exists(fileName))  {  return fileName;  }  string candidate = Path.Combine(Path.GetDirectoryName(this.TemplateFile), fileName);  if (File.Exists(candidate))  {  return candidate;  }  return fileName; } public string ResolveParameterValue(string directiveId, string processorName, string parameterName) {  if (directiveId == null)  {  throw new ArgumentNullException("the directiveId cannot be null");  }  if (processorName == null)  {  throw new ArgumentNullException("the processorName cannot be null");  }  if (parameterName == null)  {  throw new ArgumentNullException("the parameterName cannot be null");  }  return String.Empty; } public void SetFileExtension(string extension) {  FileExtension = extension; } public void SetOutputEncoding(System.Text.Encoding encoding, bool fromOutputDirective) {  FileEncoding = encoding; } public void LogErrors(CompilerErrorCollection errors) {  Errors = errors; } public AppDomain ProvideTemplatingAppDomain(string content) {  return AppDomain.CreateDomain("Generation App Domain"); } public ITextTemplatingSession CreateSession() {  return this.Session; } }}

Session

using Microsoft.VisualStudio.TextTemplating;using System;using System.Collections;using System.Collections.Generic;using System.Linq;using System.Runtime.Serialization;using System.Text;using System.Threading.Tasks;namespace CodeGenerate.EngineHost{ [Serializable] public class TextTemplatingSession : Dictionary<string, Object>, ITextTemplatingSession, ISerializable {  public Guid Id { get;private set; }  public TextTemplatingSession() : this(Guid.NewGuid())  {  }  public TextTemplatingSession(Guid id)  {   this.Id = id;  }  public override int GetHashCode()  {   return Id.GetHashCode();  }  public TextTemplatingSession(SerializationInfo info, StreamingContext context)   : base(info, context)  {   Id = (Guid)info.GetValue("Id", typeof(Guid));  }  void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)  {   base.GetObjectData(info, context);   info.AddValue("Id", Id);  }  public override bool Equals(object obj)  {   var o = obj as TextTemplatingSession;   return o != null && o.Equals(this);  }  public bool Equals(ITextTemplatingSession other)  {   return other != null && other.Id == this.Id;  }  public bool Equals(Guid other)  {   return other.Equals(Id);  } }}

入口

string templateFileName = "Template/test.tt";   TextTemplatingEngineHost host = new TextTemplatingEngineHost();   Engine engine = new Engine();   //引入本地dll   host.LocalDlls = new List<string>() { AppDomain.CurrentDomain.BaseDirectory.ToString() + "Params.dll" };   //引入命名空间   host.Namespaces = new List<string>() { "Params" };   //模板文件   host.TemplateFile = templateFileName;   //设置输出文件的编码格式   host.SetOutputEncoding(System.Text.Encoding.UTF8, false);   //通过Session将参数传递到模板   EngineHost.TextTemplatingSession keyValuePairs = new EngineHost.TextTemplatingSession();   testType t = new testType() { Name = "666666666666" };   keyValuePairs.Add("test", t);   host.Session = keyValuePairs;   //模板   string input = File.ReadAllText(templateFileName);   //执行代码生成   string output = engine.ProcessTemplate(input, host);   //设置文件的输出路径和文件扩展名 ,,根据模板中的设置定义   string outputFileName = string.Concat(    AppDomain.CurrentDomain.BaseDirectory.ToString(), "Output/",    Path.GetFileNameWithoutExtension(templateFileName),    host.FileExtension);   //将生成的文件写入到新位置   File.WriteAllText(outputFileName, output, host.FileEncoding);   if (host.Errors.HasErrors)   {    foreach (CompilerError error in host.Errors)    {     MessageBox.Show(error.ToString());    }   }

tt文件

<#@ template debug="false" hostspecific="false" language="C#" #><#@ import namespace="System.Collections.Generic" #><#@ assembly name="Params.dll" #><#@ import namespace="Params" #><#@ parameter type="Params.testType" name="test" #><#@ output extension=".cs" #><# if(test!=null&&test.Name!=null){#><#=test.Name #><# } #>

自定义参数

[Serializable] public class testType {  public string Name { get; set; } }

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对VEVB武林网的支持。


注:相关教程知识阅读请移步到c#教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表