Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I have T4 generate code based on classes in a specific namespace (Recursively)

Tags:

namespaces

c#

t4

My architecture's service layer is made up of many single purpose command classes (classes that perform one specific function on data, such as creating a user) and query classes (individual classes that query the database for specific data). These get injected into my Asp.net MVC controller classes via Windsor installers.

For example, I run container.Register(Component.For<CreateUserCommand>().ImplementedBy<CreateUserCommand>()); in my custom IWindsorInstaller class to instantiate the CreateUserCommand in my controllers.

The problem is that since each command/query class is single purpose, I will end up with a lot of these classes, and maintaining my installer class is going to be a pain in the butt. It occurred to me that this would be a perfect job for T4, as I can just run the T4 and have it regenerate the installer class to automatically register all of my command and query classes.

Unfortunately, since I have never done T4 before I don't know how to proceed to actually implement this. I have read the basics on T4, but my main point of confusion is how to actually find all of my command and query classes via T4.

On paper, I can find all my command/query classes because they are defined in the MyApp.DomainModel.Commands.* and MyApp.DomainModel.Queries.* namespaces. For example, the CreateUserCommand class resides in the MyApp.DomainModel.Queries.Users namespace. However, I have no idea how to go about actually looking through namespaces at runtime, let alone recursively.

It's possible for me to create a ICommand and IQuery interface for these classes to be based off of if that's easier to find in T4 than namespaces, but I don't know how I would find all ICommand/IQuery subclasses via T4.

I do know reflection, but from reading I have read a lot saying that using reflection in T4 is a bad idea and/or doesn't work properly.

If anyone could point me to anything that would help me accomplish this I would be greatly appreciative!

like image 427
KallDrexx Avatar asked Apr 06 '11 21:04

KallDrexx


1 Answers

Using reflection from T4 is not inherently a bad thing, but regarding "not working properly", the primary problem is that you cannot reliably reflect that current assembly in which the T4 template is defined, as this has yet to be compiled. You generally need to split your project into different assemblies in order to access your own types from T4.

Finding all types in a namespace is not a difficult issue, particularly if they're all defined in the same assembly.

<#@ 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 #>
<#  }
} 
#>
like image 137
Mark H Avatar answered Oct 15 '22 06:10

Mark H