在t4模板中读取命名空间中的类

eiu*_*165 10 t4

有没有一种方法可以在命名空间中读取并使用反射或其他东西循环遍历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);
}
<#} #>
Run Code Online (Sandbox Code Playgroud)

示例元数据:

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; } 
    }
}
Run Code Online (Sandbox Code Playgroud)

期望的输出:

    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);
    }
Run Code Online (Sandbox Code Playgroud)

Mah*_*vej 13

首先从这里安装T4Toolbox

然后在您的模板中确保您在顶部有以下行:

<#@ assembly name="EnvDTE" #> 
<#@ import namespace="EnvDTE" #>
<#@ include file="T4Toolbox.tt" #>
Run Code Online (Sandbox Code Playgroud)

然后添加以下代码行:

<#+  

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

        }
    }
}
#>
Run Code Online (Sandbox Code Playgroud)

然后你可以通过这样调用找到命名空间中的所有类(第二个参数过滤所有名称包含传递字符串的类):

FindClasses("NameSpace.SubNameSpace",""))//All classes in the specifed namespace 
Run Code Online (Sandbox Code Playgroud)

要么

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

------------------------------------------ VS 2012更新---- ----------------------

如果为VS 2012更新了T4Toolbox,请使用这些函数和命名空间:

//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);
}
Run Code Online (Sandbox Code Playgroud)

所以你的搜索将是这样的:

FindClasses(GetDefaultNamespace(),"Repository","RepositoryBase")
Run Code Online (Sandbox Code Playgroud)