C# 添加对现有注册的拦截

C# 添加对现有注册的拦截,c#,unity-container,interception,C#,Unity Container,Interception,在这个场景中,我的应用程序被交给了一个已经初始化的UnityContainer,其中注册了一个类型,可以归结为: container.RegisterType<IService>(new InjectionFactory(c => new Service())); 因此:我正在寻找一种方法,向现有的ContainerRegistration添加更多注入成员 // 1. Get the current container registration var containerRe

在这个场景中,我的应用程序被交给了一个已经初始化的
UnityContainer
,其中注册了一个类型,可以归结为:

container.RegisterType<IService>(new InjectionFactory(c => new Service()));
因此:我正在寻找一种方法,向现有的
ContainerRegistration
添加更多注入成员

// 1. Get the current container registration
var containerRegistration = container.Registrations
    .First(cr => cr.RegisteredType == typeof(IService));

// 2. Is this even possible?
ApplyInterception(
    containerRegistration,
    new Interceptor<InterfaceInterceptor>(),
    new InterceptionBehavior<ServiceInterceptor>());

// 3. Profit!
//1。获取当前容器注册
var containerRegistration=container.Registrations
.First(cr=>cr.RegisteredType==typeof(iSeries));
// 2. 这可能吗?
应用干扰(
集装箱登记,
新的拦截器(),
新的拦截行为());
// 3. 利润!

您可以首先将该类型注册为命名注册(使用InjectionFactory),同时还提供一个默认注册(没有名称)来解析命名注册:

container.RegisterType<IService>("original",
                      new InjectionFactory(c => new Service()));
container.RegisterType<IService>(
                      new InjectionFactory(c => c.Resolve<IService>("original")));
如果您现在解析
IService
,在解析“原始”命名注册时仍将使用原始工厂方法
c=>new Service()
,但这一次还将应用
serviceinceptor

我已经创建了一个完整的工作示例,您可以查看它


第二种方法是使用政策注入。(请参阅中的策略注入部分)

首先,像往常一样配置您的类型,但为使用策略注入敞开大门:

container.RegisterType<IService>(
    new InjectionFactory(c => new Service()),       
    new InterceptionBehavior<PolicyInjectionBehavior>(),
    new Interceptor<InterfaceInterceptor>());
container.RegisterType(
new InjectionFactory(c=>new Service()),
新的侦听行为(),
新拦截器());
此时,您的服务已注册,未应用任何拦截。但是,稍后您可以添加策略注入规则(例如,与您的服务类型名称相匹配),该规则将添加拦截:

container.Configure<Interception>()
    .AddPolicy("yourInterceptor")
    .AddMatchingRule<TypeMatchingRule>
        (new InjectionConstructor("MyNamespace.Service", true))
    .AddCallHandler<ServiceInterceptorHandler>(
        new ContainerControlledLifetimeManager(),
        new InjectionConstructor(),
        new InjectionProperty("Order", 1));
container.Configure()
.AddPolicy(“您的拦截器”)
.AddMatchingRule
(新的InjectionConstructor(“MyNamespace.Service”,true))
.AddCallHandler(
新建ContainerControlled LifetimeManager(),
新建InjectionConstructor(),
新的InjectionProperty(“Order”,1));
现在,如果解析
IService
,将应用
ServiceInterceptorHandler
中的拦截逻辑(该类基本上与第一种方法中的
ServiceInterceptor
相同,但实现
ICallHandler
而不是
IInterceptionBehavior

再次检查中的示例


看看这两种选择,我个人觉得第一种方法更合适,避免了匹配规则的开销

第一种方法还允许您通过再次覆盖
IService
注册来轻松地完全关闭截取,如果您希望完全关闭截取,则可以避免截取器开销。(这两种方法都允许您实现拦截器/处理程序类的
WillExecute
属性,但您仍然有拦截器的开销)。您可以使用策略注入来实现这一点,但您需要另一个中间调用处理程序,请参阅

但是,使用第二种方法,您可以使用匹配规则将此解决方案应用于多个类(例如名称空间中的所有类,或名称遵循特定模式的所有类,等等。您可以查看匹配规则)


最后你需要决定哪一个最适合你。(可能还有其他方法,希望能看到它们发布!)

感谢您的提示-命名类型注册现在似乎很明显:)我添加了一个命名类型注册,其中包括一个注射厂解决原始未命名注册(即您建议的oposite),并将拦截器添加到新的命名注册中。这似乎很有效。但真的没有办法访问和修改当前的类型注册条目吗-SI除了覆盖当前注册之外,不知道有什么方法可以修改它。当然不是通过成员为只读的
ContainerRegistration
类。也可以选择使用,但这本质上是覆盖初始配置的另一种方式。子容器方法引导我走上了一条最终在Nowheresville的道路:)
container.RegisterType<IService>(
    new InjectionFactory(c => new Service()),       
    new InterceptionBehavior<PolicyInjectionBehavior>(),
    new Interceptor<InterfaceInterceptor>());
container.Configure<Interception>()
    .AddPolicy("yourInterceptor")
    .AddMatchingRule<TypeMatchingRule>
        (new InjectionConstructor("MyNamespace.Service", true))
    .AddCallHandler<ServiceInterceptorHandler>(
        new ContainerControlledLifetimeManager(),
        new InjectionConstructor(),
        new InjectionProperty("Order", 1));