Genere múltiples archivos con T4 (reproducido)

Genere múltiples archivos con T4 (reproducido)

Transferencia desde: http://blog.csdn.net/cracklibby/article/details/51319799

Cuando reconocí por primera vez y traté de usar T4 para generar código, parecía haber relativamente pocos materiales de aprendizaje relevantes. Pero ahora hay capítulos relacionados en MSDN de VS2010, puede consultar el capítulo "Generación de código y plantillas de texto". Puede escribir plantillas en sintaxis de C #, que es mucho más cómodo.

Pronto se hizo evidente que T4 tenía dificultades para generar múltiples archivos, y Microsoft no parecía apresurarse a mejorar esto. A través de la búsqueda, encontré un artículo " Generando múltiples archivos con T4 " de InfoQ , vinculando a un artículo, la extensión Damien Guard puede generar fácilmente múltiples archivos. El texto original está en inglés, lo que se puede entender, pero si se traduce, es muy difícil considerar las palabras.

Primero, guarde el siguiente código como un archivo de plantilla (por ejemplo, guarde el archivo como Manager.ttinclude):

<# @ assembly name = "System.Core" #>  
<# @ assembly name = "System.Data.Linq" #>  
<# @ assembly name = "EnvDTE" #>  
<# @ assembly name = "System.Xml" #>  
<# @ assembly name = "System.Xml.Linq" #>  
<# @ import namespace = "Sistema" #>  
<# @ import namespace = "System.CodeDom" #>  
<# @ import namespace = "System.CodeDom.Compiler" #>  
<# @ import namespace = "System.Collections.Generic" #>  
<# @ import namespace = "System.Data.Linq" #>  
<# @ import namespace = "System.Data.Linq.Mapping" #>  
<# @ import namespace = "System.IO" #>  
<# @ import namespace = "System.Linq" #>  
<# @ import namespace = "System.Reflection" #>  
<# @ import namespace = "System.Text" #>  
<# @ import namespace = "System.Xml.Linq" #>  
<# @ import namespace = "Microsoft.VisualStudio.TextTemplating" #>  
<# +  
   
// La clase Manager registra los distintos bloques para poder dividirlos  
Gerente de clase {  
    Bloque de clase privada {  
        Nombre de cadena pública;  
        public int Start, Length;  
    }  
   
    Bloque privado currentBlock;  
    Lista privada <Block> archivos = nueva Lista <Block> ();  
    pie de página de bloque privado = nuevo bloque ();  
    Encabezado de bloque privado = nuevo bloque ();  
    host privado ITextTemplatingEngineHost;  
    plantilla privada de StringBuilder;  
    Lista protegida <String> generateFileNames = nueva Lista <String> ();  
   
    Public static Manager Create (host ITextTemplatingEngineHost, plantilla StringBuilder) {  
        return (el host es IServiceProvider)? nuevo VSManager (host, plantilla): nuevo Manager (host, plantilla);  
    }  
   
    public void StartNewFile (String name) {  
        if (nombre == nulo)  
            lanzar una nueva ArgumentNullException ("nombre");  
        CurrentBlock = nuevo bloque {Name = name};  
    }  
   
    StartFooter público vacío () {  
        CurrentBlock = pie de página;  
    }  
   
    StartHeader public void () {  
        CurrentBlock = encabezado;  
    }  
   
    public void EndBlock () {  
        if (CurrentBlock == nulo)  
            regreso;  
        CurrentBlock.Length = template.Length - CurrentBlock.Start;  
        if (CurrentBlock! = encabezado && CurrentBlock! = pie de página)  
            archivos.Add (CurrentBlock);  
        currentBlock = nulo;  
    }  
   
    Proceso público virtual vacío (bool split) {  
        si (dividido) {  
            EndBlock ();  
            String headerText = template.ToString (header.Start, header.Length);  
            String footerText = template.ToString (footer.Start, footer.Length);  
            Cadena outputPath = Path.GetDirectoryName (host.TemplateFile);  
            archivos.Reverse ();  
            foreach (Bloquear bloque en archivos) {  
                String fileName = Path.Combine (outputPath, block.Name);  
                Contenido de cadena = headerText + template.ToString (block.Start, block.Length) + footerText;  
                generateFileNames.Add (fileName);  
                CreateFile (nombre de archivo, contenido);  
                template.Remove (block.Start, block.Length);  
            }  
        }  
    }  
   
    CreateFile virtual vacío protegido (String fileName, String content) {  
        if (IsFileContentDifferent (nombre de archivo, contenido))  
            File.WriteAllText (nombre de archivo, contenido);  
    }  
   
    cadena virtual pública GetCustomToolNamespace (String fileName) {  
        volver nulo;  
    }  
   
    cadena virtual pública DefaultProjectNamespace {  
        get {return null; }  
    }  
   
    bool protegido IsFileContentDifferent (String fileName, String newContent) {  
        return! (File.Exists (fileName) && File.ReadAllText (fileName) == newContent);  
    }  
   
    Administrador privado (host ITextTemplatingEngineHost, plantilla StringBuilder) {  
        this.host = host;  
        this.template = template;  
    }  
   
    Bloque privado CurrentBlock {  
        get {return currentBlock; }  
        establecer {  
            if (CurrentBlock! = nulo)  
                EndBlock ();  
            if (valor! = nulo)  
                value.Start = template.Length;  
            currentBlock = valor;  
        }  
    }  
   
    VSManager clase privada: Gerente {  
        EnvDTE.ProjectItem privado templateProjectItem;  
        EnvDTE.DTE privado dte;  
        Acción privada <String> checkOutAction;  
        Acción privada <IEnumerable <String>> projectSyncAction;  
   
        anulación pública Cadena DefaultProjectNamespace {  
            obtener {  
                return templateProjectItem.ContainingProject.Properties.Item ("DefaultNamespace"). Value.ToString ();  
            }  
        }  
   
        anulación pública String GetCustomToolNamespace (string fileName) {  
            return dte.Solution.FindProjectItem (fileName) .Properties.Item ("CustomToolNamespace"). Value.ToString ();  
        }  
   
        Proceso de anulación de anulación pública (división de bool) {  
            if (templateProjectItem.ProjectItems == null)  
                regreso;  
            base.Process (split);  
            projectSyncAction.EndInvoke (projectSyncAction.BeginInvoke (generateFileNames, null, null));  
        }  
   
        anulación protegida anular CreateFile (String fileName, String content) {  
            if (IsFileContentDifferent (fileName, content)) {  
                CheckoutFileIfRequired (fileName);  
                File.WriteAllText (nombre de archivo, contenido);  
            }  
        }  
   
        VSManager interno (host ITextTemplatingEngineHost, plantilla StringBuilder)  
            : base (host, plantilla) {  
            var hostServiceProvider = (IServiceProvider) host;  
            if (hostServiceProvider == nulo)  
                lanzar una nueva ArgumentNullException ("No se pudo obtener IServiceProvider");  
            dte = (EnvDTE.DTE) hostServiceProvider.GetService (typeof (EnvDTE.DTE));  
            if (dte == nulo)  
                lanzar una nueva ArgumentNullException ("No se pudo obtener DTE del host");  
            templateProjectItem = dte.Solution.FindProjectItem (host.TemplateFile);  
            checkOutAction = (String fileName) => dte.SourceControl.CheckOutItem (fileName);  
            projectSyncAction = (IEnumerable <String> keepFileNames) => ProjectSync (templateProjectItem, keepFileNames);  
        }  
   
        privado estático vacío ProjectSync (EnvDTE.ProjectItem templateProjectItem, IEnumerable <String> keepFileNames) {  
            var keepFileNameSet = new HashSet <String> (keepFileNames);  
            var projectFiles = new Dictionary <String, EnvDTE.ProjectItem> ();  
            var originalFilePrefix = Path.GetFileNameWithoutExtension (templateProjectItem.get_FileNames (0)) + ".";  
            foreach (EnvDTE.ProjectItem projectItem en templateProjectItem.ProjectItems)  
                projectFiles.Add (projectItem.get_FileNames (0), projectItem);  
   
            // Eliminar elementos no utilizados del proyecto  
            foreach (par var en projectFiles)  
                if (! keepFileNames.Contains (pair.Key) &&! (Path.GetFileNameWithoutExtension (pair.Key) + "."). StartsWith (originalFilePrefix))  
                    pair.Value.Delete ();  
   
            // Agregar archivos faltantes al proyecto  
            foreach (String fileName en keepFileNameSet)  
                if (! projectFiles.ContainsKey (fileName))  
                    templateProjectItem.ProjectItems.AddFromFile (nombreDeArchivo);  
        }  
   
        privado vacío CheckoutFileIfRequired (String fileName) {  
            var sc = dte.SourceControl;  
            if (sc! = nulo && sc.IsItemUnderSCC (nombre de archivo) &&! sc.IsItemCheckedOut (nombre de archivo))  
                checkOutAction.EndInvoke (checkOutAction.BeginInvoke (nombreDeArchivo, nulo, nulo));  
        }  
    }  
} #>  

 

A continuación, haga referencia a esta plantilla en el archivo de plantilla T4 y declare una instancia de la clase Manager:

<# @ template language = "C #" hostspecific = "True" #>  
<# @ include file = "Manager.ttinclude" #>  
<# var manager = Manager.Create (Host, GenerationEnvironment); #>  

 

El uso de dos líneas de código puede hacer que el código salga a un archivo separado. El código que desea generar puede escribirse en medio de estas dos declaraciones. El parámetro de StartNewFile es el nombre del archivo de salida:

<# manager.StartNewFile ("Employee.generated.cs"); #>  
  
<# manager.EndBlock (); #>  

 

Por ejemplo, puedes escribir:

<# manager.StartNewFile ("Employee.generated.cs"); #>  
Empleado de clase pública {}  
<# manager.EndBlock (); #>  

 

También puede generar el mismo encabezado o encabezado para cada archivo de salida, solo necesita la declaración correspondiente:

<# manager.StartHeader (); #>  
// Código generado por una plantilla  
utilizando el sistema;  
<# manager.EndBlock (); #>  
   
<# manager.StartFooter (); #>  
// Es el final  
<# manager.EndBlock (); #>  

 

Finalmente use esta oración para realizar la salida de múltiples archivos:

<# manager.Process (verdadero); #>  

 

17 artículos originales publicados · Me gusta 230 · Visitas 340,000+

Supongo que te gusta

Origin blog.csdn.net/cxu123321/article/details/105514714
Recomendado
Clasificación