好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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://HdhCmsTestcnblogs测试数据/zzfstudy/p/9796816.html

dy("nrwz");

查看更多关于C#如何通过T4自动生成代码详解的详细内容...

  阅读:68次