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")
}
);
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.