2010-10-13 12 views
9

Czy istnieje sposób, w jaki można odczytać w przestrzeni nazw i przechodzić przez wszystkie klasy w szablonie t4 za pomocą odbicia lub coś takiego?Czytanie klas w przestrzeni nazw w szablonie 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); 
} 
<#} #> 

przykład dane meta:

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; } 
    } 
} 

pożądane wyjście:

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

Odpowiedz

13

Najpierw zainstaluj T4Toolbox from here

Następnie w szablonie zapewnić Państwu następujące linie na górze:

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

Następnie dodaj te linie kodów:

<#+ 

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

     } 
    } 
} 
#> 

Następnie można znaleźć wszystkie klasy w obszarze nazw, wywołując w ten sposób (drugi parametr filtruje wszystkie zajęcia, które ich nazwy zawierają przeszedł String):

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

LUB

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

- ---------------------------------------- AKTUALIZACJA DLA VS 2012 ------ --------------------

Użyj tych funkcji i przestrzeni nazw, jeśli Twój T4Toolbox jest aktualizowany dla 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); 
} 

więc wyszukiwanie będzie coś takiego:

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

Uwaga: W VS2012 'TransformationContext 'uległo zmianie: http://www.olegsych.com/2012/12/t4-toolbox-for-visual-studio-2012/ – kamranicus

+1

@subkamran yes! Poprawię post w wersji 2012 jak najszybciej ... –

+0

Używam VS2012 z twoim zaktualizowanym kodem i zawiera EnvDTE.dll w moim projekcie, ale to mówi 'IVsSolution',' SVsSolution', 'IVsHierarchy' nie można znaleźć w ciągu plik .tt. Jakieś pomysły? – JimmyBoh

0
+0

Linki do potencjalnych rozwiązań są zawsze mile widziane, ale dodaj kilka szczegółów dla przyszłych użytkowników, jeśli link jest nie jest już dostępny –

1

Używam T4 w rdzeniu projektu .net,

Moja T4 jest dość duży, więc po prostu wyodrębnianie istotnych informacji tutaj .. [W moim przypadku szukam Entity Framework modeli i wiem, że są to jedyne zajęcia w przestrzeni nazw, może trzeba odfiltrować własne]

odwołujące te pakiety 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" #> 

te import/obejmuje:

<#@ 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" #> 

mam tej metody:

// 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; 
    } 

i wywołać ją przy użyciu: (wymienić "App.Data.Model.Entities" z własnych)

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

Skąd pochodzi dteHelper? – Cesar

Powiązane problemy