Как я могу заставить T4 генерировать код на основе классов в определенном пространстве имен (рекурсивно)

Сервисный уровень моей архитектуры состоит из множества одноцелевых командных классов (классов, которые выполняют одну конкретную функцию над данными, например, создание пользователя) и классов запросов (отдельных классов, которые запрашивают у базы данных определенные данные). Они внедряются в мои классы контроллера Asp.net MVC через установщики Windsor.

Например, я запускаю 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. Однако я понятия не имею, как на самом деле просматривать пространства имен во время выполнения, не говоря уже о рекурсии.

Я могу создать интерфейс ICommand и IQuery для этих классов, если их легче найти в T4, чем в пространствах имен, но я не знаю, как найти все подклассы ICommand/IQuery через T4.

Я знаю отражение, но из чтения я много читал о том, что использование отражения в T4 - плохая идея и/или не работает должным образом.

Если бы кто-нибудь мог указать мне на что-нибудь, что помогло бы мне достичь этого, я был бы очень признателен!


person KallDrexx    schedule 06.04.2011    source источник


Ответы (1)


Использование отражения из 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 #>
<#  }
} 
#>
person Mark H    schedule 06.04.2011