如何让T4根据特定命名空间中的类生成代码(递归)

Kal*_*exx 5 c# t4 namespaces

我的体系结构的服务层由许多单用途命令类(对数据执行一个特定功能的类,如创建用户)和查询类(查询数据库以查找特定数据的各个类)组成.这些通过Windsor安装程序注入我的Asp.net MVC控制器类.

例如,我container.Register(Component.For<CreateUserCommand>().ImplementedBy<CreateUserCommand>());在我的自定义IWindsorInstaller类中运行以CreateUserCommand在我的控制器中实例化.

问题在于,由于每个命令/查询类都是单一的目的,我最终将会遇到很多这样的类,并且维护我的安装程序类将是一个痛苦的屁股.在我看来,对于T4来说这将是一个完美的工作,因为我可以运行T4并让它重新生成安装程序类以自动注册我的所有命令和查询类.

不幸的是,因为在我不知道如何进行实际实现之前我从未做过T4.我已经阅读了T4的基础知识,但我的主要困惑是如何通过T4实际找到我的所有命令和查询类.

在纸面上,我可以找到所有命令/查询类,因为它们是在MyApp.DomainModel.Commands.*MyApp.DomainModel.Queries.*名称空间中定义的.例如,CreateUserCommand该类驻留在MyApp.DomainModel.Queries.Users命名空间中.但是,我不知道如何在运行时实际查看命名空间,更不用说递归了.

我可以为这些类创建一个ICommandIQuery接口,如果在T4中比命名空间更容易找到,但我不知道如何ICommand/IQuery通过T4 找到所有子类.

我确实知道反思,但是从阅读中我已经阅读了很多说在T4中使用反射是一个坏主意和/或无法正常工作.

如果有人能指出任何有助于我实现这一目标的事情,我将非常感激!

Mar*_*k H 8

使用来自T4的反射本身并不是一件坏事,但是对于"不正常工作",主要问题是您无法可靠地反映定义了T4模板的当前程序集,因为尚未编译.您通常需要将项目拆分为不同的程序集,以便从T4访问您自己的类型.

查找命名空间中的所有类型并不是一个难题,特别是如果它们都在同一个程序集中定义的话.

<#@ import namespace = "System.Reflection" #>
<# 
var path="D:\Path\To\MyApp.DomainModel.dll";
Assembly a = Assembly.ReflectionOnlyLoadFrom(path);
foreach (var type in a.GetTypes()) {
    if (type.Namespace == "MyApp.DomainModel.Commands") { #>
        <#=type.Name #>
<#  }
} 
#>
Run Code Online (Sandbox Code Playgroud)