unity-containerunity-interception

Unity InterceptionBehavior with InjectionConstructor


Is it possible to configure a custom InterceptionBehavior with InjectionConstructor? In other words, how do you tell Unity which constructor on your InterceptionBehavior to use.

In order to trace the method flow in our application, I currently have four InterceptionBehavior classes that deal with tracing. The only difference between them is the TraceSwitch that they use in order to configure tracing, so we can turn on/off tracing in the different layers. I would like to only have one custom TraceInterceptionBehavior, which I could use ConstructorInjection in order to set the TraceSwitches.

Something like this (example only, does not compile). This would be where I register the business services into the container. There would be similar registrations for the other layers such as controllers and repositories etc.

container.RegisterTypes(
    serviceTypes,
    WithMappings.FromMatchingInterface,
    getLifetimeManager: WithLifetime.ContainerControlled,
    getInjectionMembers: c => new InjectionMember[]
    {
        new Interceptor<InterfaceInterceptor>(),
        new InterceptionBehavior<TraceInterceptionBehavior>(
        // this is how I would do it if interception behavior supported constructor injection
                    new InjectionConstructor(new ResolvedParameter<ITracer>(), 
                                             TraceSwitches.ServiceBegin, 
                                             TraceSwitches.ServiceEnd))

            });
    }

The constructor of the custom TraceInterceptionBehavior that I am trying to call:

public TraceInterceptionBehavior(ITracer tracer, TraceSwitch traceSwitchBegin, TraceSwitch traceSwitchEnd) : this(tracer)
{
    TraceSwitchBegin = traceSwitchBegin;
    TraceSwitchEnd = traceSwitchEnd;
}

As I understand, this is possible if using the PolicyInjection and CallHandler from the older Unity such as the following example but I am at a loss on how to do it with the new version of Unity.

container.Configure<Interception>()
.AddPolicy("SomePolicyName")
.AddCallHandler<SomeCustomInterceptor>(
    new InjectionConstructor(new ResolvedParameter<SomeType>(), new ResolvedParameter<SomeType2>());

Update

As pointed out by @DanielJ.G below, the interception behavior class can be registered into the container just like any other class. For each layer that I want trace interception using a different trace switch, I just set up a named registration for the interception behavior. The below code would be for the service layer. There are similar registrations for controllers and repositories using a different name and traceswitch configuration.

container.RegisterType<TraceInterceptionBehavior>("ServiceTraceInterceptionBehavior",
    new ContainerControlledLifetimeManager(),
    new InjectionConstructor(new ResolvedParameter<ITracer>(),
    TraceSwitches.ServiceBegin,
    TraceSwitches.ServiceEnd));

container.RegisterTypes(
    serviceTypes,
    WithMappings.FromMatchingInterface,
    getLifetimeManager: WithLifetime.ContainerControlled,
    getInjectionMembers: c =>
    new InjectionMember[]
        {
            new Interceptor<InterfaceInterceptor>(),
            new InterceptionBehavior<TraceInterceptionBehavior> "ServiceTraceInterceptionBehavior")
        }
    );

Solution

  • You can configure TraceInterceptionBehavior as if it were any of the registered types in Unity, so you could add the following to your container registration:

    container.RegisterType<TraceInterceptionBehavior>(
        new InjectionConstructor(new ResolvedParameter<ITracer>(), 
                                 TraceSwitches.ServiceBegin, 
                                 TraceSwitches.ServiceEnd));
    

    You have a full sample in this fiddle.