Register the same Unity hook and call handler for all registered types

I have an ICallHandler that I want to register in all instances of the Unity container.

For example, take the following handler:

public class ProfilerHandler : ICallHandler { public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) { //start timer IMethodReturn methodReturn = getNext()(input, getNext); //stop timer } public int Order { get; set; } } 

And the following IoC container constructor:

 public class IoCContainer : UnityContainer { public IoCContainer() { this.RegisterType<IUserService, UserService>(new ContainerControlledLifetimeManager()); this.RegisterType<IRepository<User>, UserRepository>(new ContainerControlledLifetimeManager()); } } 

All I want to do is register this handler with all of these types.

I can do this with some pretty detailed code:

 public class IoCContainer : UnityContainer { public IoCContainer() { this.AddNewExtension<Interception>(); this.RegisterType<IUserService, UserService>(new ContainerControlledLifetimeManager()).Configure<Interception>().SetInterceptorFor<IUserService>(new InterfaceInterceptor()); this.RegisterType<IRepository<User>, UserRepository>(new ContainerControlledLifetimeManager()).Configure<Interception>().SetInterceptorFor<IRepository<User>>(new InterfaceInterceptor()); } } 

But I not only have to write the same interception code in all my type registers (imagine if I have more than 100 types registered), but I also need to enable HandlerAttribute on each interface (again, not bad if I have more 100 interfaces to apply this).

Is this my only option or is there a way to do this at the container level to avoid having to apply it to each individual registration and type interface?

+6
source share
1 answer

Unity 3 provides registration by agreement , which can help in this scenario:

 IUnityContainer container = new UnityContainer(); container.AddNewExtension<Interception>(); container.RegisterTypes( AllClasses.FromLoadedAssemblies().Where( t => t.Namespace == "My.Namespace.Services"), WithMappings.MatchingInterface, getInjectionMembers: t => new InjectionMember[] { new Interceptor<InterfaceInterceptor>(), new InterceptionBehavior<MyBehavior>() }); } 

You could combine the above with Injection Policy to use the appropriate rules for connecting a call handler. Thus, you can use different matching rules instead of (or in combination with) attributes to determine which call handlers come with which classes / methods.

 container.RegisterTypes( AllClasses.FromLoadedAssemblies().Where( t => t.Namespace == "My.Namespace.Services"), WithMappings.MatchingInterface, getInjectionMembers: t => new InjectionMember[] { new InterceptionBehavior<PolicyInjectionBehavior>(), new Interceptor<InterfaceInterceptor>(), }); } container.Configure<Interception>() .AddPolicy("profiler") .AddMatchingRule<AssemblyMatchingRule>( new InjectionConstructor( new InjectionParameter("My.Namespace.Services"))) .AddCallHandler<ProfilerHandler>( new ContainerControlledLifetimeManager()); 

Unity 2 also supports policy implementation.

An alternative to registration by agreement would be to write a Unity Container Extension to post interception during registration.

+9
source

Source: https://habr.com/ru/post/949057/


All Articles