just part of the crowd
just part of the crowd

Reputation: 227

Unity Interception using auto wiring

I got Unity interception working using a HadlerAttribute and an instance of ICallHandler. To get it working all I have to do is decorate the class with the [Trace] attribute, and the interceptor works great.

  [Trace]
public interface IPersonService
{
    string GetPerson();
}

However I would like to have interception working for all my methods in a couple of assemblies. So I am using Unity AutoRegistration to set up my container as follows:

private static IUnityContainer BuildUnityContainer()
    {
        var container = new UnityContainer();

        //container.AddNewExtension<UnityInterfaceInterceptionRegisterer>();

        container.
            ConfigureAutoRegistration().
            ExcludeSystemAssemblies().  
            LoadAssemblyFrom(typeof(PersonService).Assembly.Location).
            Include(If.ImplementsITypeName, Then.Register()).
            ApplyAutoRegistration();


        return container;
    }

Works great, except when I attempt to setup global registration as per this post: http://unity.codeplex.com/discussions/281022

I have a UnityContainerExtension configured as follows, where MVC4Unity is my DLL:

public class UnityInterfaceInterceptionRegisterer : UnityContainerExtension
{
    protected override void Initialize()
    {
        base.Container.AddNewExtension<Interception>();

        base.Container.Configure<Interception>().
            AddPolicy("LoggingPolicy").
            AddMatchingRule<AssemblyMatchingRule>
            (new InjectionConstructor("MVC4Unity")).
            AddCallHandler(new TraceCallHandler()); 


        base.Context.Registering += new EventHandler<RegisterEventArgs>(this.OnRegister);
    }

    private void OnRegister(object sender, RegisterEventArgs e)
    {
        IUnityContainer container = sender as IUnityContainer;

        if (e != null && e.TypeFrom != null && e.TypeFrom.IsInterface)
        {
            container.Configure<Interception>()
                .SetInterceptorFor(e.TypeFrom, e.Name, new InterfaceInterceptor());
        }
    }
}

Unfortunately it is always throwing a StackOverflowException (!) when it goes into the OnRegister method.

The question then is, has anyone implemented assembly or even namespace wide interception using Unity, and was this the way to go?

[EDIT]

It seems that no matter what I add in the AddMatchingRule line below, that the OnRegister handler is invoked for all included assemblies as well! ( for example even the Microsoft.* namespace assemblies!)

base.Container.AddNewExtension<Interception>();

        base.Container.Configure<Interception>().
            AddPolicy("LoggingPolicy").
            // see what other types of matchings rules there are!
            AddMatchingRule<NamespaceMatchingRule>
            (new InjectionConstructor("MVC4Unity.*")).
            AddCallHandler(new TraceCallHandler()); 


        base.Context.Registering += new EventHandler<RegisterEventArgs>(this.OnRegister);

Upvotes: 1

Views: 936

Answers (1)

Val
Val

Reputation: 539

I'm late with my answer, but maybe someone will find this useful.

  • If I understood the problem correctly you need to apply one matching rule to multiple assemblies. For these kind of tasks you can use AssemblyMatchingRule (MSDN).

    container.Configure<Interception>()
      .AddPolicy("logging")
      .AddMatchingRule<AssemblyMatchingRule>(
         new InjectionConstructor(
         new InjectionParameter("YourAssemblyName")))
      .AddCallHandler<LoggingCallHandler>(
         new ContainerControlledLifetimeManager(),
         new InjectionConstructor(), new InjectionProperty("Order", 1));
    
  • In your last code snippet i think you need to remove dot asterisk in the end of namespace in order to add MVC4Unity namespace to your NamespaceMatchingRule.


For additional information please check this link - Policy Injection MSDN

Upvotes: 1

Related Questions