我們使用CreateClassProxy
方法爲服務創建代理,因爲它是在對問題Castle Dynamic Proxy not intercepting method calls when invoked from within the class的回答中提出的。 然後我們將獲得的代理註冊爲接口的實現。 所以我們的定製RegisterComponent
方法看起來像這樣
private void RegisterComponent<TInterface, TImplementation>()
where TInterface : class
where TImplementation : class, TInterface
{
var proxyType = new ProxyGenerator().CreateClassProxy<TImplementation>().GetType();
Container.Register(Component.For<TInterface>().ImplementedBy(proxyType));
}
完整的組件註冊爲
Container = new WindsorContainer();
Container.Kernel.Resolver.AddSubResolver(new CollectionResolver(Container.Kernel));
// Interceptor
Container.Register(Component.For<IInterceptor>().ImplementedBy<SomeInterceptor>().LifestyleTransient());
// Component registrations
RegisterComponent<ISomeService, SomeService>();
,當然,你需要攔截所有的方法應該是virtual
由於使用了基於繼承的代理。
但是這種解決方案的缺點是在創建代理對象時不能使用構造函數注入。 請注意,您正在使用new
運算符創建「虛擬」代理對象,以獲取代理的類型。因此,只有在構建虛擬代理時才能使用構造函數注入,但是當通過容器解析服務時,注入將會很好地工作。所以這個缺點僅對於構建邏輯比僅依賴分配更復雜的組件來說至關重要。如果你只需要依賴assigments你可以嘗試創建虛擬代理
private object[] ResolveConstructorParameters<TType>()
{
return typeof(TType).GetConstructors()
.Single(c => c.IsPublic)
.GetParameters()
.Select(p => _container.Resolve(p.ParameterType))
.ToArray();
}
之前手動解決從容器中的所有依賴關係,然後RegisterComponent
將成爲
private void RegisterComponent<TInterface, TImplementation>()
where TInterface : class
where TImplementation : class, TInterface
{
var constructorParameters = ResolveConstructorParameters<TImplementation>();
var proxyType = new ProxyGenerator().CreateClassProxy(typeof(TImplementation), constructorParameters).GetType();
_container.Register(Component.For<TInterface>().ImplementedBy(proxyType));
}
您也可以只需填寫論點null
。
有什麼方式來註冊服務作爲接口,但使用基於繼承的攔截沒有這個黑客?爲什麼它默認禁用? – xumix
不幸的是我不知道,它可以讓你改變默認的攔截機制的任何開關,但我從來沒有真的需要這所以從來沒有真正開始認真的。我通常在應用層服務上使用攔截來完成事務管理等事情。所以在我的情況下,它並沒有太大的SENS有這種行爲(例如,如果外攔截方法調用期間已經打開的事務我不希望爲內部方法調用再次發生)。 –
@剋日什托夫·-kozmic所以有使用基於繼承攔截沒有簡單的方法? – xumix