2010-10-13 6 views
9

¿Hay alguna manera de leer en un espacio de nombres y recorrer todas las clases en una plantilla t4 usando reflexión o algo así?Leer clases en un espacio de nombres en una plantilla t4

<#foreach (class poco in LoadNamespace("Web.Code.Entities.Poco").Classes) { #> 
public interface I<# poco.ClassName #>Repository 
{ 
    IQueryable< <# poco.ClassName #> > Get(); 
    <# poco.ClassName #> Save(<# poco.ClassName #> entity); 
    bool Delete(<# poco.ClassName #> entity); 
} 
<#} #> 

ejemplo de metadatos:

namespace Web.Code.Entities.Poco 
{ 
    public class Product 
    { 
      public int Id { get; set; } 
      public string Name{ get; set; } 
      public string Category{ get; set; } 
    } 

    public class Employee 
    { 
      public int Id { get; set; } 
      public string Name{ get; set; } 
    } 
} 

salida deseada:

public interface IProductRepository 
    { 
     IQueryable<Product> Get(); 
     Product Save(Product entity); 
     bool Delete(Product entity); 
    } 

    public interface IEmployeeRepository 
    { 
     IQueryable<Employee> Get(); 
     Employee Save(Employee entity); 
     bool Delete(Employee entity); 
    } 
+0

http://www.dreamincode.net/code/snippet1539.htm – eiu165

Respuesta

13

Primero instale T4Toolbox from here

A continuación, en la plantilla de asegurarse de que tiene las siguientes líneas en la parte superior:

<#@ assembly name="EnvDTE" #> 
<#@ import namespace="EnvDTE" #> 
<#@ include file="T4Toolbox.tt" #> 

Entonces agregue estas líneas de códigos:

<#+ 

private List<CodeClass> FindClasses(string nameSpace, string className) 
{ 
    List<CodeClass> result=new List<CodeClass>(); 
    FindClasses(TransformationContext.Project.CodeModel.CodeElements,className,nameSpace,result,false); 
    return result; 

} 


private void FindClasses(CodeElements elements, string className,string searchNamespace,List<CodeClass> result,bool isNamespaceOk) 
{ 
    if (elements==null)return; 
    foreach (CodeElement element in elements) 
    {  
     if(element is CodeNamespace) 
     { 
      CodeNamespace ns = element as CodeNamespace; 
      if(ns != null) 
      { 
       if (ns.FullName == searchNamespace) 
        FindClasses(ns.Members, className,searchNamespace,result,true); 
       else 
        FindClasses(ns.Members, className,searchNamespace,result,false); 
      } 
     } 
     else if(element is CodeClass && isNamespaceOk) 
     { 
      CodeClass c = element as CodeClass; 
      if (c != null) 
      { 
       if(c.FullName.Contains(className)) 
        result.Add(c); 

       FindClasses(c.Members, className,searchNamespace,result,true); 
      } 

     } 
    } 
} 
#> 

entonces usted puede encontrar todas las clases en un espacio de nombres, llamando así (el segundo parámetro filtra todas las clases que sus nombres contienen la cadena pasada):

FindClasses("NameSpace.SubNameSpace",""))//All classes in the specifed namespace 

O

FindClasses("NameSpace.SubNameSpace","Repository")) //All classes in the specifed namespace which have "Repository" in their names 

- ---------------------------------------- ACTUALIZACIÓN PARA VS 2012 ------ --------------------

Utilice estas funciones y espacios de nombres si su T4Toolbox se actualiza para VS 2 012:

//visual studio 2012+ 
<#@ assembly name="Microsoft.VisualStudio.Shell.11.0" #> 
<#@ assembly name="Microsoft.VisualStudio.Shell.Interop" #> 
<#@ import namespace="Microsoft.VisualStudio.Shell" #> 
<#@ import namespace="Microsoft.VisualStudio.Shell.Interop" #> 

private List<CodeClass> FindClasses(string nameSpace, string className,string baseClassName) 
{ 
    List<CodeClass> result=new List<CodeClass>(); 
    FindClasses(GetProject().CodeModel.CodeElements,className,baseClassName,nameSpace,result,false); 
    return result; 

} 


private void FindClasses(CodeElements elements, string className,string baseClassName,string searchNamespace,List<CodeClass> result,bool isNamespaceOk) 
{ 
    if (elements==null)return; 
    foreach (CodeElement element in elements) 
    {  
     if(element is CodeNamespace) 
     { 
      CodeNamespace ns = element as CodeNamespace; 
      if(ns != null) 
      { 
       if (ns.FullName == searchNamespace) 
        FindClasses(ns.Members, className,baseClassName,searchNamespace,result,true); 
       else 
        FindClasses(ns.Members, className,baseClassName,searchNamespace,result,false); 
      } 
     } 
     else if(element is CodeClass && isNamespaceOk) 
     { 
      CodeClass c = element as CodeClass; 
      if (c != null) 
      { 
       if(c.FullName.Contains(className) && (baseClassName==null || (HasIt(c.Bases ,baseClassName) && c.Name != baseClassName))) 
        result.Add(c); 

       FindClasses(c.Members, className,baseClassName,searchNamespace,result,true); 
      } 

     } 
    } 
} 

private bool HasIt(CodeElements elements,string name) 
{ 
    foreach (CodeElement element in elements) 
    { 
     if (element.Name==name) 
      return true; 
    } 
    return false; 
} 

private Project GetProject() 
{ 
    // Get DTE 
    var dte = (DTE)TransformationContext.Current.GetService(typeof(DTE)); 

    // Get ProjectItem representing the template file 
    ProjectItem projectItem = dte.Solution.FindProjectItem(TransformationContext.Current.Host.TemplateFile); 

    // Get the Project of the template file 
    Project project = projectItem.ContainingProject; 

    return project; 
} 

private string GetDefaultNamespace() 
{ 

    // Get DTE 
    var dte = (DTE)TransformationContext.Current.GetService(typeof(DTE)); 

    // Get ProjectItem representing the template file 
    ProjectItem projectItem = dte.Solution.FindProjectItem(TransformationContext.Current.Host.TemplateFile); 

    // Get the Project of the template file 
    Project project = projectItem.ContainingProject; 

    var vsSolution = (IVsSolution)TransformationContext.Current.GetService(typeof(SVsSolution)); 
    IVsHierarchy vsHierarchy; 
    ErrorHandler.ThrowOnFailure(vsSolution.GetProjectOfUniqueName(project.FullName, out vsHierarchy)); 
    uint projectItemId; 
    ErrorHandler.ThrowOnFailure(vsHierarchy.ParseCanonicalName(projectItem.FileNames[1], out projectItemId)); 
    object defaultNamespace; 
    ErrorHandler.ThrowOnFailure(vsHierarchy.GetProperty(projectItemId, (int)VsHierarchyPropID.DefaultNamespace, out defaultNamespace)); 
    return ((string)defaultNamespace); 
} 

por lo que su búsqueda será algo como esto:

FindClasses(GetDefaultNamespace(),"Repository","RepositoryBase") 
+0

Nota: En VS2012 'TransformationContext 'ha cambiado: http://www.olegsych.com/2012/12/t4-toolbox-for-visual-studio-2012/ – kamranicus

+1

@subkamran ¡sí! Voy a corregir el post con la versión 2012 lo antes posible ... –

+0

estoy usando VS2012 con su código actualizado e incluido EnvDTE.dll en mi proyecto, pero es mucho decir 'IVsSolution',' SVsSolution', 'IVsHierarchy' no se encuentra dentro de el archivo .tt. ¿Algunas ideas? – JimmyBoh

0
+0

Enlaces a las posibles soluciones son siempre bienvenidos, pero por favor, añadir algunos detalles para futuros visitantes en caso de que el enlace es. ya no está disponible. –

1

estoy usando T4 en un proyecto central .net,

Mi T4 es bastante grande, por lo que acaba de extraer la información relevante aquí .. [En mi caso estoy en busca de modelos de Entity Framework y sé que estas son las únicas clases del espacio de nombres, puede que tenga que filtrar sus propios]

referencia a estos paquetes NuGet:

<#@ assembly name="$(UserProfile)\.nuget\packages\Microsoft.VisualStudio.TextTemplating.Interfaces.14.0\14.3.25407\lib\net45\Microsoft.VisualStudio.TextTemplating.Interfaces.14.0.dll" #> 
<#@ assembly name="$(UserProfile)\.nuget\packages\Microsoft.VisualStudio.TextTemplating.14.0\14.3.25407\lib\net45\Microsoft.VisualStudio.TextTemplating.14.0.dll" #> 

éstos importaciones/incluye:

<#@ import namespace="EnvDTE" #> 
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #> 
<#@ import namespace="Microsoft.VisualStudio.TextTemplating.Interfaces" #> 
<#@ include file="$(UserProfile)\.nuget\packages\T4.VsAutomationHelper\1.0.0\tools\ttinc\VsAutomationHelper.CS.ttinclude" #> 
<#@ include file="$(UserProfile)\.nuget\packages\T4.TemplateFileManager\2.2.1\tools\ttinc\TemplateFilemanager.CS.ttinclude" #> 

tengo este método:

// Get all CodeClass Items in specified namespace 
    public List<EnvDTE.CodeClass> GetClassesInNameSpace(IEnumerable<ProjectItem> items, string nameSpace) 
    { 
     var classItems = new List<EnvDTE.CodeClass>(); 

     var csFileProjectItems = items.Where(d => d.Properties.Item("FullPath").Value.ToString().EndsWith(".cs")); 

     foreach(ProjectItem csFileProjectItem in csFileProjectItems) 
     { 
      EnvDTE.FileCodeModel model = csFileProjectItem.FileCodeModel; 
      foreach(var modelCodeElements in model.CodeElements) 
      { 
       if (modelCodeElements is EnvDTE.CodeNamespace) 
       { 
        var codeNameSpace = ((EnvDTE.CodeNamespace)modelCodeElements); 

        if (codeNameSpace.FullName == nameSpace) 
        { 
         foreach(var modelCodeElementChild in codeNameSpace.Children) 
         { 
          if (modelCodeElementChild is EnvDTE.CodeClass) 
          { 
           classItems.Add((EnvDTE.CodeClass)modelCodeElementChild); 
          } 
         } 
        } 
       } 
      } 
     } 
     return classItems; 
    } 

y llamarlo usando: (sustituir "App.Data.Model.Entities" con su propio)

var projectItems = this.dteHelper.GetAllProjectItems(); 
     var entityClasses = GetClassesInNameSpace(projectItems, "App.Data.Model.Entities"); 

    foreach (var entityClass in entityClasses) 
    { 
     // entityClass.Name 

     // Important for .NetCore 
     // when calling fileManager.StartNewFile() specify all the parameters, its didn't work for me otherwise eg: 
     // code appreciated (file manager created before following code) 

     var fileProperties = new FileProperties() 
{ 
    BuildAction = BuildAction.Compile 
}; 
     fileManager.StartNewFile(dataAccessFileName, generatedFilesTargetProject, generatedFilesTargetFolder, fileProperties); 
    fileManager.IsAutoIndentEnabled = true; 
    fileManager.CanOverwriteExistingFile = true; 
    } 
+0

¿De dónde viene dteHelper? – Cesar

Cuestiones relacionadas