软件编程
位置:首页>> 软件编程>> C#编程>> C#如何通过T4自动生成代码详解

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

作者:FreeTimeWorker  发布时间:2021-12-21 15:43:46 

标签:c#,t4,自动生成代码

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; }
}

来源:https://www.cnblogs.com/zzfstudy/p/9796816.html

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com