nhibernatedependency-injectioncastle-windsorproxy-classes

Implementing .Net DI Compile Time Proxies?


I'm not so much seeking a specific implementation but trying to figure out the proper terms for what I'm trying to do so I can properly research the topic.

I have a bunch of interfaces and those interfaces are implemented by controllers, repositories, services and whatnot. Somewhere in the start up process of the application we're using the Castle.MicroKernel.Registration.Component class to register the classes to use for a particular interface. For instance:

Component.For<IPaginationService>().ImplementedBy<PaginationService>().LifeStyle.Transient

Recently I became interested in creating an audit trail of every class and method call. There's a few hundred of these classes so writing a proxy class for each one by hand isn't very practical. I could use a template to generate the code but I'd rather not blow up our code base with all that.

So I'm curious if there's some kind of on the fly solution. I know nHibernate creates proxy classes at some point which overlay all the entity classes. Can someone give me some guidance on how I might be able to do something similar here?

Something like:

Component.For<IPaginationService>().ImplementedBy<ProxyFor<PaginationService>>().LifeStyle.Transient

Obviously that won't work because I can only use generics to generalize the types of methods but not the methods themselves. Is there some tricky reflection approach I can use to do this?


Solution

  • You are looking for what Castle Windsor calls interceptors. It's an aspect-oriented way to tackle cross-cutting concerns -- auditing is certainly one of them. See documentation, or an article about the approach:

    Aspect oriented programming is an approach that effectively “injects” pieces of code before or after an existing operation. This works by defining an Inteceptor wrapping the logic being invoked then registering it to run whenever a particular set/sub-set of methods are called.

    If you want to apply it to many registered services, read more about interceptor selection mechanisms: IModelInterceptorsSelector helps there.

    Using PostSharp, things like this can be even done at compile time. This can speed the resulting application, but when used correctly, interceptors are not slow.