C# 通过T4自动生成代码

2018/10/16 11:09
阅读数 89

通过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;
        }
    }
}
View Code

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);
        }
    }
}
View Code

入口

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());
                }
            }
View Code

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 #>
<#    } #>
View Code

自定义参数

 [Serializable]
    public class testType
    {
        public string Name { get; set; }
    }
View Code
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部