Avoiding SetInterceptorFor with Unity 3

Feb 7, 2014 at 9:44 AM

I have developed a TransactionInterceptor and a TransactionAttribute which I am using to mark methods that I want to be transactional. At the moment my registration code looks like this:
         /* Register transaction matching rule and call handler */
            container.RegisterType<IMatchingRule, TransactionMatchingRule>("transactionMatchingRule");
            container.RegisterType<ICallHandler, TransactionInterceptor>("transactionInterceptor");

            /* Create transaction policy and reference the matching rule and call handler by name */

            //TODO - there must be a way of not having to do this for every service...
            container.Configure<Interception>().SetInterceptorFor<IProductService>(new TransparentProxyInterceptor());
            container.Configure<Interception>().SetInterceptorFor<INestedTestService>(new TransparentProxyInterceptor());
In order to avoid having to call SetInterceptorFor for every object that I want to be intercepted should I do something similar to the suggestions in these threads:

or is there a Unity 3 way of doing all of this that would be better?

Feb 7, 2014 at 12:07 PM
With Unity 3 you can use Registration by Convention to apply the interception injection member.

The Developer's Guide has an example similar to this:
var container = new UnityContainer();

      t => t.Namespace == "MyNamespace"), // or some other way of getting your services
    getInjectionMembers: t => new InjectionMember[]
      new Interceptor<TransparentProxyInterceptor>(),
      new InterceptionBehavior<PolicyInjectionBehavior>()
Now if the target classes don't really have any "convention" to follow then the above might not help. That would probably indicate a bit of a design issue but in practice it can happen.

Randy Levy
Enterprise Library support engineer
Support How-to
Feb 7, 2014 at 12:14 PM
Thanks for the reply. To be honest I've always stayed away from automatically loading all components by convention because you might have different implementations of different interfaces that are used in different builds/environments. I suppose you could try to organise them all by namespace or something like that, but it could get messy.
Feb 7, 2014 at 12:34 PM
Yes, it can get messy. One approach to get around this might be to create a custom RegistrationConvention that returns the exact types you want without using assembly scanning and applies the injection members. It's still cleaner than a custom container extension, IMO.

Randy Levy
Enterprise Library support engineer
Support How-to
Feb 7, 2014 at 1:35 PM
Ok cool, thanks for all the different suggestions. I've mainly used Spring.NET and Castle before so I'm fairly new to Unity. I might look into that last suggestion later. For now I've just gone for a simple solution (an extension method). If I decide to stick with this i'll probably overload it to take different lifetime manager proxy interceptor types.
public static IUnityContainer RegisterTypeWithProxy<TFrom, TTo>(this IUnityContainer container) where TTo : TFrom
    container.RegisterType<TFrom, TTo>(new ContainerControlledLifetimeManager())
        .Configure<Interception>().SetInterceptorFor<TFrom>(new TransparentProxyInterceptor());

    return container;