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

时间:2011-04-06 21:40:52

标签: c# namespaces t4

我的架构的服务层由许多单用途命令类(对数据执行一个特定功能的类,如创建用户)和查询类(查询数据库以查找特定数据的各个类)组成。这些通过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中使用反射是一个坏主意和/或无法正常工作。

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

1 个答案:

答案 0 :(得分: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 #>
<#  }
} 
#>