You could initially register the type as a named registration (using the InjectionFactory) while also providing a default registration (with no name) that just resolves the named registration:
container.RegisterType<IService>("original",
new InjectionFactory(c => new Service()));
container.RegisterType<IService>(
new InjectionFactory(c => c.Resolve<IService>("original")));
So you can resolve IService
as you would normally do. However you will now be able to replace the default registration while keeping the original named registration. This way you can work around your issue, where you couldn't re-register IService
due to the factory statement not being available at that point.
With this approach in place, at a later point you can override the default IService
registration with one where interception is registered and still uses the original named registration for resolving the instance:
container.RegisterType<IService>(
new InjectionFactory(c => c.Resolve<IService>("original")),
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<ServiceInterceptor>());
If you now resolve IService
, you will still use the original factory method c => new Service()
as it is resolving the "original" named registration, but this time your ServiceInterceptor
is also applied.
I have created this fiddle so you can check a full working example.
There is a second approach using Policy Injection. (See Policy Injection section in the msdn).
First configure your type as usual, but leave the door opened for using Policy Injection:
container.RegisterType<IService>(
new InjectionFactory(c => new Service()),
new InterceptionBehavior<PolicyInjectionBehavior>(),
new Interceptor<InterfaceInterceptor>());
At this point your service is registered without any interception being applied. However at a later point you can add a policy injection rule, for example matching your service type name, that adds the interception:
container.Configure<Interception>()
.AddPolicy("yourInterceptor")
.AddMatchingRule<TypeMatchingRule>
(new InjectionConstructor("MyNamespace.Service", true))
.AddCallHandler<ServiceInterceptorHandler>(
new ContainerControlledLifetimeManager(),
new InjectionConstructor(),
new InjectionProperty("Order", 1));
Now if you resolve IService
, the interception logic in ServiceInterceptorHandler
will be applied (This class is basically the same as ServiceInterceptor
in the first approach, but implementing ICallHandler
instead of IInterceptionBehavior
)
Again, check the example in this fiddle
Having a look at both options, I personally feel more comfortable with the first approach, avoiding the overhead of the matching rules.
The first approach would also allow you to easily completely turn off interception by overriding again the IService
registration, saving you from the interceptors overhead if you want it completely off. (Both approaches allow you to implement the WillExecute
property of the interceptor/handler classes, but you still have the overhead of the interceptors). You can do this using policy injection, but you need another intermediate call handler, see this post
However with the second approach, you could apply this solution to multiple classes using the matching rules (For example all classes in a namespace, or all classes whose name follows a specific pattern, etc. You can take a look at the matching rules here)
In the end you will need to decide which one fits you best. (and there might be other approaches, would love to see them posted!)