Как я могу T4 генерировать код на основе классов в определенном пространстве имен (рекурсивно) - PullRequest
5 голосов
/ 07 апреля 2011

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

Например, я запускаю container.Register(Component.For<CreateUserCommand>().ImplementedBy<CreateUserCommand>()); в своем пользовательском IWindsorInstaller классе, чтобы создать экземпляр CreateUserCommand в моих контроллерах.

Проблема заключается в том, что каждый класс команды / запроса имеет одну цельЯ закончу с большим количеством этих классов, и поддержание моего класса установщика будет болью в заднице.Мне пришло в голову, что это будет идеальная работа для T4, так как я могу просто запустить T4 и заставить его заново создать класс установщика для автоматической регистрации всех моих команд и классов запросов.

К сожалению, так как у меня естьЯ никогда не делал Т4, пока не знаю, как на самом деле реализовать это.Я прочитал основы T4, но моя главная путаница в том, как на самом деле найти все мои классы команд и запросов через T4.

На бумаге я могу найти все свои классы команд / запросов, поскольку они определены в пространствах имен MyApp.DomainModel.Commands.* и MyApp.DomainModel.Queries.*.Например, класс CreateUserCommand находится в пространстве имен MyApp.DomainModel.Queries.Users.Тем не менее, я понятия не имею, как на самом деле просматривать пространства имен во время выполнения, не говоря уже о рекурсивном.

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

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

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

1 Ответ

8 голосов
/ 07 апреля 2011

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