view raw
KallDrexx KallDrexx - 6 months ago 29
C# Question

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

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 MVC controller classes via Windsor installers.

For example, I run

in my custom
class to instantiate the
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
namespaces. For example, the
class resides in the
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
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
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!


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 #>
<#  }