7

我有一个 ICallHandler,我想在我的所有 Unity 容器实例中注册它。

例如,采用以下处理程序:

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;
    }
}

以及以下 IoC 容器构造函数:

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

我想做的就是用所有这些类型注册这个处理程序。

我可以用一些非常冗长的代码来做到这一点:

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());
    }
}

但我不仅必须在所有类型注册上编写相同的拦截代码(想象一下,如果我有 100 多个类型注册),而且我还必须HandlerAttribute在每个接口上包含一个(同样,如果我有 100 多个接口将此应用于)。

这是我唯一的选择,还是有办法在容器级别执行此操作以避免将其应用于每个单独的类型注册和接口?

4

1 回答 1

10

Unity 3按约定提供注册,这在这种情况下可能会有所帮助:

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>()
    });
}

您可以将上述内容与策略注入结合使用匹配规则来连接您的呼叫处理程序。这样,您可以使用各种匹配规则而不是(或结合使用)属性来确定哪些调用处理程序与哪些类/方法一起使用。

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 还支持策略注入。

按照惯例注册的替代方法是编写一个 Unity Container Extension 以在注册期间执行拦截的连接。

于 2013-07-09T22:02:35.510 回答