zoukankan      html  css  js  c++  java
  • T4随记

    关于T4模板的信息我就不赘述了,百度一大堆

    MSDN的介绍 https://msdn.microsoft.com/zh-cn/library/bb126478.aspx

    下面是简单的一个示例,从类中获取字符串数组,并生成数组相应的类文件

    需要一个MultipleOutputHelper.ttinclude文件,你也可以百度下载,

    新建一个模板文件,重命名为MultipleOutputHelper.ttinclude,然后写入如下内容,不需要任何修改

    <#@ assembly name="System.Core"
    #><#@ assembly name="System.Data.Linq"
    #><#@ assembly name="EnvDTE"
    #><#@ assembly name="System.Xml"
    #><#@ assembly name="System.Xml.Linq"
    #><#@ import namespace="System.Collections.Generic"
    #><#@ import namespace="System.IO"
    #><#@ import namespace="System.Text"
    #><#@ import namespace="Microsoft.VisualStudio.TextTemplating"
    #><#+
    // https://raw.github.com/damieng/DamienGKit
    // http://damieng.com/blog/2009/11/06/multiple-outputs-from-t4-made-easy-revisited
    
    // Manager class records the various blocks so it can split them up
    class Manager {
        private class Block {
            public String Name;
            public int Start, Length;
            public bool IncludeInDefault;
        }
    
        private Block currentBlock;
        private readonly List<Block> files = new List<Block>();
        private readonly Block footer = new Block();
        private readonly Block header = new Block();
        private readonly ITextTemplatingEngineHost host;
        private readonly StringBuilder template;
        protected readonly List<String> generatedFileNames = new List<String>();
    
        public static Manager Create(ITextTemplatingEngineHost host, StringBuilder template) {
            return (host is IServiceProvider) ? new VSManager(host, template) : new Manager(host, template);
        }
    
        public void StartNewFile(String name) {
            if (name == null)
                throw new ArgumentNullException("name");
            CurrentBlock = new Block { Name = name };
        }
    
        public void StartFooter(bool includeInDefault = true) {
            CurrentBlock = footer;
            footer.IncludeInDefault = includeInDefault;
        }
    
        public void StartHeader(bool includeInDefault = true) {
            CurrentBlock = header;
            header.IncludeInDefault = includeInDefault;
        }
    
        public void EndBlock() {
            if (CurrentBlock == null)
                return;
            CurrentBlock.Length = template.Length - CurrentBlock.Start;
            if (CurrentBlock != header && CurrentBlock != footer)
                files.Add(CurrentBlock);
            currentBlock = null;
        }
    
        public virtual void Process(bool split, bool sync = true) {
            if (split) {
                EndBlock();
                String headerText = template.ToString(header.Start, header.Length);
                String footerText = template.ToString(footer.Start, footer.Length);
                String outputPath = Path.GetDirectoryName(host.TemplateFile);
                files.Reverse();
                if (!footer.IncludeInDefault)
                    template.Remove(footer.Start, footer.Length);
                foreach(Block block in files) {
                    String fileName = Path.Combine(outputPath, block.Name);
                    String content = headerText + template.ToString(block.Start, block.Length) + footerText;
                    generatedFileNames.Add(fileName);
                    CreateFile(fileName, content);
                    template.Remove(block.Start, block.Length);
                }
                if (!header.IncludeInDefault)
                    template.Remove(header.Start, header.Length);
            }
        }
    
        protected virtual void CreateFile(String fileName, String content) {
            if (IsFileContentDifferent(fileName, content))
                File.WriteAllText(fileName, content);
        }
    
        public virtual String GetCustomToolNamespace(String fileName) {
            return null;
        }
    
        public virtual String DefaultProjectNamespace {
            get { return null; }
        }
    
        protected bool IsFileContentDifferent(String fileName, String newContent) {
            return !(File.Exists(fileName) && File.ReadAllText(fileName) == newContent);
        }
    
        private Manager(ITextTemplatingEngineHost host, StringBuilder template) {
            this.host = host;
            this.template = template;
        }
    
        private Block CurrentBlock {
            get { return currentBlock; }
            set {
                if (CurrentBlock != null)
                    EndBlock();
                if (value != null)
                    value.Start = template.Length;
                currentBlock = value;
            }
        }
    
        private class VSManager: Manager {
            private readonly EnvDTE.ProjectItem templateProjectItem;
            private readonly EnvDTE.DTE dte;
            private readonly Action<String> checkOutAction;
            private readonly Action<List<String>> projectSyncAction;
    
            public override String DefaultProjectNamespace {
                get {
                    return templateProjectItem.ContainingProject.Properties.Item("DefaultNamespace").Value.ToString();
                }
            }
    
            public override String GetCustomToolNamespace(string fileName) {
                return dte.Solution.FindProjectItem(fileName).Properties.Item("CustomToolNamespace").Value.ToString();
            }
    
            public override void Process(bool split, bool sync) {
                if (templateProjectItem.ProjectItems == null)
                    return;
                base.Process(split, sync);
                if (sync)
                    projectSyncAction.EndInvoke(projectSyncAction.BeginInvoke(generatedFileNames, null, null));
            }
    
            protected override void CreateFile(String fileName, String content) {
                if (IsFileContentDifferent(fileName, content)) {
                    CheckoutFileIfRequired(fileName);
                    File.WriteAllText(fileName, content);
                }
            }
    
            internal VSManager(ITextTemplatingEngineHost host, StringBuilder template)
                : base(host, template) {
                var hostServiceProvider = (IServiceProvider)host;
                if (hostServiceProvider == null)
                    throw new ArgumentNullException("Could not obtain IServiceProvider");
                dte = (EnvDTE.DTE) hostServiceProvider.GetService(typeof(EnvDTE.DTE));
                if (dte == null)
                    throw new ArgumentNullException("Could not obtain DTE from host");
                templateProjectItem = dte.Solution.FindProjectItem(host.TemplateFile);
                checkOutAction = fileName => dte.SourceControl.CheckOutItem(fileName);
                projectSyncAction = keepFileNames => ProjectSync(templateProjectItem, keepFileNames);
            }
    
            private static void ProjectSync(EnvDTE.ProjectItem templateProjectItem, List<String> keepFileNames) {
                var keepFileNameSet = new HashSet<String>(keepFileNames);
                var projectFiles = new Dictionary<String, EnvDTE.ProjectItem>();
                var originalFilePrefix = Path.GetFileNameWithoutExtension(templateProjectItem.FileNames[0]) + ".";
                foreach (EnvDTE.ProjectItem projectItem in templateProjectItem.ProjectItems)
                    projectFiles.Add(projectItem.FileNames[0], projectItem);
    
                // Remove unused items from the project
                foreach (var pair in projectFiles)
                    if (!keepFileNames.Contains(pair.Key) && !(Path.GetFileNameWithoutExtension(pair.Key) + ".").StartsWith(originalFilePrefix))
                        pair.Value.Delete();
    
                // Add missing files to the project
                foreach(String fileName in keepFileNameSet)
                    if (!projectFiles.ContainsKey(fileName))
                        templateProjectItem.ProjectItems.AddFromFile(fileName);
            }
    
            private void CheckoutFileIfRequired(String fileName) {
                var sc = dte.SourceControl;
                if (sc != null && sc.IsItemUnderSCC(fileName) && !sc.IsItemCheckedOut(fileName))
                    checkOutAction.EndInvoke(checkOutAction.BeginInvoke(fileName, null, null));
            }
        }
    } #>
    View Code

    新建一个类TestList,内容如下

     public class TestList
        {
            public List<string> GetList()
            {
                return new List<string>() { "Name1","Name2","Name3"};
            }
        }

    然后新建一个模板文件,model.tt,写入内容如下

    <#@ template debug="false" hostspecific="true" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ assembly name="$(TargetPath)" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Collections.Generic" #>
    <#@ import namespace="TestAutoFac.Bll"#>
    <#@include file="../MultipleOutputHelper.ttinclude"#> 
    
    <#
    
         var manager = Manager.Create(Host, GenerationEnvironment);  
        TestList tl=new TestList();
        List<string> lst=tl.GetList();foreach (var item in lst)
        {
            manager.StartNewFile(item+".cs");
    //下面生成代码
             #>
    
    using System;
    public class  <#=item#>
    {
        public <#=item#>()
        {}
    }
    
             <#
    //上面生成代码
              manager.EndBlock(); 
        }
         manager.Process(true);  
    #>
    解释:<#@ assembly name="$(TargetPath)" #>   引入dll文件,这里用了vs的宏,指的是当前项目的dll
    <#@include file="../MultipleOutputHelper.ttinclude"#> :引入根目录下的MultipleOutputHelper.ttinclude
    <#@ import namespace="TestAutoFac.Bll"#>:引入TestList的命名空间
    剩下的就没有说明了 ,看下项目的结构
    红色划掉的是没用的

    看下Name1.cs

    大概就这样了 ,记录下 备忘



  • 相关阅读:
    【原创】虚拟机上实现绑定固定IP扩主机容器互访
    docker entrypoint入口文件详解
    数据库博客推荐
    docker下centos安装ping命令
    Dockerfile指令详解
    Elasticsearch Java API 的使用
    docker容器里面安装ssh
    RPM安装命令总结
    Docker容器的跨主机连接
    使用Java程序片段动态生成表格
  • 原文地址:https://www.cnblogs.com/bfyx/p/9895501.html
Copyright © 2011-2022 走看看