2014-10-29 51 views
3

添加攔截在這種情況下我我的申請被移交已初始化上UnityContainer已經註冊的類型,其歸結爲:現有註冊

container.RegisterType<IService>(new InjectionFactory(c => new Service())); 

我需要實現的是加入一個攔截器ServiceInterceptorIService註冊。我想明顯的答案是:通過運行第二個RegisterType<IService>並將攔截器作爲注入成員來執行此操作。但是,如下所述重新創建提供的注塑工廠和代表是不可行的。此時我無法獲得new Service()聲明。

container.RegisterType<IService>(
    new InjectionFactory(c => new Service()), 
    new Interceptor<InterfaceInterceptor>(), 
    new InterceptionBehavior<ServiceInterceptor>()); 

所以:我正在尋找一種方法來添加進一步的注射成員到現有的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! 

回答

3

你可以開始註冊類型爲命名註冊(使用InjectionFactory),同時還提供了一個默認註冊(沒有名字),只是解決了一個名爲登記:

container.RegisterType<IService>("original", 
         new InjectionFactory(c => new Service())); 
container.RegisterType<IService>(
         new InjectionFactory(c => c.Resolve<IService>("original"))); 

這樣你就可以像平常一樣解決IService。但是,您現在可以在保留原始指定註冊的同時替換默認註冊。通過這種方式,您可以解決您的問題,因爲此時工廠聲明不可用,所以無法重新註冊IService

有了這個方法,在以後可以覆蓋默認IService登記一個地方攔截註冊並仍然使用原來的命名註冊解決實例:

container.RegisterType<IService>(
    new InjectionFactory(c => c.Resolve<IService>("original")), 
    new Interceptor<InterfaceInterceptor>(), 
    new InterceptionBehavior<ServiceInterceptor>()); 

如果現在解決IService,您仍將使用原始工廠方法c => new Service(),因爲它正在解析「原始」指定註冊,但這次您的ServiceInterceptor也被應用。

我已經創建this fiddle,所以你可以檢查一個完整的工作示例。


有使用政策注入第二種方法。 (請參閱the msdn中的策略注入部分)。

首先設置你的型像往常一樣,但留下的門打開,使用政策注射:

container.RegisterType<IService>(
    new InjectionFactory(c => new Service()),  
    new InterceptionBehavior<PolicyInjectionBehavior>(), 
    new Interceptor<InterfaceInterceptor>()); 

此時你的服務是沒有應用任何攔截註冊。不過在稍後的時候,你可以添加一個策略注入規則,例如符合您服務類型名,增加了攔截:如果你解決IService

container.Configure<Interception>() 
    .AddPolicy("yourInterceptor") 
    .AddMatchingRule<TypeMatchingRule> 
     (new InjectionConstructor("MyNamespace.Service", true)) 
    .AddCallHandler<ServiceInterceptorHandler>(
     new ContainerControlledLifetimeManager(), 
     new InjectionConstructor(), 
     new InjectionProperty("Order", 1)); 

現在,ServiceInterceptorHandler攔截邏輯將被應用(這班是基本相同的第一種方法ServiceInterceptor,但實施ICallHandler代替IInterceptionBehavior

再次,檢查在示例this fiddle


看看這兩個選項,我個人對第一種方法感到更加滿意,避免了匹配規則的開銷。

第一種方法還允許您輕鬆完全關閉攔截,方法是再次覆蓋IService註冊,如果您希望完全關閉攔截器,則可以將其從攔截器的開銷中解救出來。 (這兩種方法都允許你實現攔截器/處理器類的WillExecute屬性,但是你仍然有攔截器的開銷)。爲此,您可以使用策略注入,但你需要另一箇中間呼叫處理程序,請參見this post

然而,在第二種方法,可以將這個解決方案使用匹配的規則命名空間中的應用到多個類別(例如,所有類,或所有類別的名稱都遵循特定模式,等等。您可以查看匹配規則here

最後,您需要決定哪一個最適合您。 (也有可能是其他的方法,希望能看到他們發佈!)

+0

謝謝你的提示 - 命名類型註冊現在似乎如此明顯:) 我添加了一個名爲類型註冊,包括注射工廠解決原未命名的註冊(即反駁您的建議),並將攔截器添加到新的指定註冊中。這似乎很好地工作。 但是真的沒有辦法訪問和修改當前的類型註冊條目嗎? -S – 2014-10-31 12:26:34

+0

我不知道有任何修改當前註冊的方式,而不是覆蓋它。當然不能通過其成員只讀的'ContainerRegistration'類。 – 2014-10-31 12:41:51

+0

也有使用[子容器](http://msdn.microsoft.com/en-us/library/dn507462(v = pandp.30).aspx)的選項,但這基本上是覆蓋初始值的另一種方式配置 – 2014-10-31 12:48:41