C#如何通過T4自動生成代碼詳解
T4簡介
T4(Text Template Transformation Toolkit)在 Visual Studio 中,“T4 文本模板”是由一些文本塊和控制邏輯組成的混合模板,它可以生成文本文件。 在 Visual C# 或 Visual Basic 中,控制邏輯編寫為程序代碼的片段。生成的文件可以是任何類型的文本,例如網(wǎng)頁、資源文件或任何語言的程序源代碼。
T4 文本模板有兩種類型:
1、運(yùn)行時模板
可在應(yīng)用程序中執(zhí)行運(yùn)行時 T4 文本模板(“預(yù)處理過的”模板)以便生成文本字符串(通常作為其輸出的一部分)。
若要創(chuàng)建運(yùn)行時模板,請向您的項目中添加“已預(yù)處理的文本模板”文件。
另外,您還可以添加純文本文件并將其“自定義工具”屬性設(shè)置為“TextTemplatingFilePreprocessor”。
2、設(shè)計時模板
在 Visual Studio 中執(zhí)行設(shè)計時 T4 文本模板,以便定義應(yīng)用程序的部分源代碼和其他資源。
通常,您可以使用讀取單個輸入文件或數(shù)據(jù)庫中的數(shù)據(jù)的多個模板,并生成一些 .cs、.vb 或其他源文件。
每個模板都生成一個文件。 在 Visual Studio 或 MSBuild 內(nèi)執(zhí)行它們。
若要創(chuàng)建設(shè)計時模板,請向您的項目中添加“文本模板”文件。 另外,您還可以添加純文本文件并將其“自定義工具”屬性設(shè)置為“TextTemplatingFileGenerator”。
通過T4模板生成代碼,運(yùn)行時實(shí)現(xiàn)
關(guān)鍵代碼段: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>
/// 文件擴(kuò)展名
/// </summary>
public string FileExtension { get; set; }
/// <summary>
/// 文件擴(kuò)展名
/// </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>
/// 參數(shù)傳遞
/// </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;
//設(shè)置輸出文件的編碼格式
host.SetOutputEncoding(System.Text.Encoding.UTF8, false);
//通過Session將參數(shù)傳遞到模板
EngineHost.TextTemplatingSession keyValuePairs = new EngineHost.TextTemplatingSession();
testType t = new testType() { Name = "666666666666" };
keyValuePairs.Add("test", t);
host.Session = keyValuePairs;
//模板
string input = File.ReadAllText(templateFileName);
//執(zhí)行代碼生成
string output = engine.ProcessTemplate(input, host);
//設(shè)置文件的輸出路徑和文件擴(kuò)展名 ,,根據(jù)模板中的設(shè)置定義
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 #>
<# } #>
自定義參數(shù)
[Serializable]
public class testType
{
public string Name { get; set; }
}
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。
相關(guān)文章
C#使用Twain協(xié)議開發(fā)一個高掃儀對接功能
這篇文章主要為大家詳細(xì)介紹了C#如何使用Twain協(xié)議開發(fā)一個高掃儀對接功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-02-02

