我正在Castle Windsor進行攔截實驗,並注意到攔截器似乎是作爲我的服務接口的裝飾器創建的。換句話說,如果我有一個接口「ISomethingDoer」和一個具體的「ConcreteSomethingDoer」,代理實現ISomethingDoer但不從ConcreteSomethingDoer繼承。使用Castle Windsor攔截具體實現(與服務相反)使用Castle Windsor
這是好的,毫無疑問的設計,但我想知道的是,我是否可以在我的具體類中攔截受保護的虛擬方法,這些方法不會被公共接口知道。我這樣做是爲了添加日誌記錄支持,但我可能想記錄一些類的特定內部細節。
在我稍有想象力的測試用例我有這樣的:
public interface ISomethingDoer
{
void DoSomething(int Count);
}
[Loggable]
public class ConcreteSomethingDoer : ISomethingDoer
{
public void DoSomething(int Count)
{
for (var A = 0; A < Count; A++)
{
DoThisThing(A);
}
}
[Loggable]
protected virtual void DoThisThing(int A)
{
("Doing a thing with " + A.ToString()).Dump();
}
}
所以我想要做的是日誌調用「DoThisThing」,即使它不是接口的一部分。
我已經設法讓Autofac中的這個工作。 (我創建這裏Linqpad腳本:http://share.linqpad.net/frn5a2.linq),但正與溫莎城堡掙扎(見http://share.linqpad.net/wn7877.linq)
在這兩種情況下,我的攔截器是一樣的,看起來像這樣:
public class Logger : IInterceptor
{
public void Intercept(IInvocation Invocation)
{
String.Format("Calling method {0} on type {1} with parameters {2}",
Invocation.Method.Name,
Invocation.InvocationTarget.GetType().Name,
String.Join(", ", Invocation.Arguments.Select(a => (a ?? "*null*").ToString()).ToArray())).Dump();
Invocation.Proceed();
"Done".Dump();
}
}
我真正想要的要做的是說「任何具有[Loggable]屬性的類,都應該使用日誌攔截器」。在Autofac例如我已經明確地連接一個記錄器進行登記,而與城堡我使用IModelInterceptorsSelector看起來像這樣:
public class LoggerInterceptorSelector : IModelInterceptorsSelector
{
public bool HasInterceptors(ComponentModel Model)
{
return Model.Implementation.IsDefined(typeof(LoggableAttribute), true);
}
public InterceptorReference[] SelectInterceptors(ComponentModel Model, InterceptorReference[] Interceptors)
{
return new[]
{
InterceptorReference.ForType<Logger>()
};
}
}
最後,執行此所有的代碼是:
var Container = new WindsorContainer();
Container.Register(
Component.For<Logger>().LifeStyle.Transient
);
Container.Kernel.ProxyFactory.AddInterceptorSelector(new LoggerInterceptorSelector());
Container.Register(
Component.For<ISomethingDoer>()
.ImplementedBy<ConcreteSomethingDoer>()
.LifeStyle.Transient
);
var Doer = Container.Resolve<ISomethingDoer>();
Doer.DoSomething(5);
運行時,我希望每次調用該方法時都會看到「使用參數x調用方法DoThisThing」。相反,我只接到對DoSomething記錄的調用。
我可以看到爲什麼溫莎城堡這樣做,但我想知道是否有辦法調整行爲?
(作爲一個側面說明,我不希望使用溫莎自己的攔截器屬性,因爲我不希望我的介紹根組成的外部依賴性城堡。)
我已經試過專門解決ConcreteSomethingDoer這是有效的,但如果我正在解決ISomethingDoer問題,則不行。
對於這篇較長的文章感到抱歉,同時也很抱歉,因爲我對溫莎城堡相當陌生!
啊,這是偉大的,作品一種享受 - 非常感謝你!我對此還是有點新鮮感,之前沒有遇到類型轉發......從我可以收集的這意味着「對於ISomethingDoer,使用與ConcreteSomethingDoer相同的註冊」,然後它只向容器註冊ConcreteSomethingDoer? (我也可以擺脫「.ImplementedBy」來使用自我註冊,這也起作用)。 – John 2013-04-05 15:12:00
註冊後,您可以通過ISomethingDoer或ConcreteSomethingDoer來解析ConcreteSomethingDoer。副作用是強制生成類代理。 – Marwijn 2013-04-07 11:30:44
的逗號分隔的有關條款語法簡單轉發的快捷方式 - 即以下應該工作,以及: Component.For() .ImplementedBy () 的.forward () –
Bermo
2014-03-10 02:01:17