這是與其他地方所述的類似的模式,並且詳述了in this blog post。我已經在使用Windsor 2.5.4,正如博客文章中所述,但決定轉用Windsor 3.當我這樣做時,我注意到應用程序的內存使用量隨着時間推移而上升 - 我猜想這會是組件不會被釋放。Castle Windsor 3攔截器不釋放由打字工廠創建的組件,但是2.5.4做過。爲什麼?
博客文章中的代碼有幾處修改,這可能會導致行爲有所不同。
這裏是我的自動釋放攔截器(直出的博文,在這裏爲方便和懶惰;))
[Transient]
public class AutoReleaseHandlerInterceptor : IInterceptor
{
private static readonly MethodInfo Execute = typeof(IDocumentHandler).GetMethod("Process");
private readonly IKernel _kernel;
public AutoReleaseHandlerInterceptor(IKernel kernel)
{
_kernel = kernel;
}
public void Intercept(IInvocation invocation)
{
if (invocation.Method != Execute)
{
invocation.Proceed();
return;
}
try
{
invocation.Proceed();
}
finally
{
_kernel.ReleaseComponent(invocation.Proxy);
}
}
}
一位來自博客文章我的偏差是選擇了類型化的工廠使用: -
public class ProcessorSelector : DefaultTypedFactoryComponentSelector
{
protected override Func<IKernelInternal, IReleasePolicy, object> BuildFactoryComponent(MethodInfo method,
string componentName,
Type componentType,
IDictionary additionalArguments)
{
return new MyDocumentHandlerResolver(componentName,
componentType,
additionalArguments,
FallbackToResolveByTypeIfNameNotFound,
GetType()).Resolve;
}
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return null;
}
protected override Type GetComponentType(MethodInfo method, object[] arguments)
{
var message = arguments[0];
var handlerType = typeof(IDocumentHandler<>).MakeGenericType(message.GetType());
return handlerType;
}
}
什麼可能是值得注意的是,我不使用默認的解析器。 (這也許是問題所在......)。
public class MyDocumentHandlerResolver : TypedFactoryComponentResolver
{
public override object Resolve(IKernelInternal kernel, IReleasePolicy scope)
{
return kernel.Resolve(componentType, additionalArguments, scope);
}
}
(爲簡潔起見,我沒有特別說明,它只是稱爲基本ctor)。
我這樣做的原因是因爲默認解析器會嘗試按名稱解析而不是按類型解析並且失敗。在這種情況下,我知道我只需要按類型來解析,所以我只是覆蓋了Resolve方法。
拼圖的最後一部分將是安裝程序。
container.AddFacility<TypedFactoryFacility>()
.Register(
Component.For<AutoReleaseHandlerInterceptor>(),
Component.For<ProcessorSelector>().ImplementedBy<ProcessorSelector>(),
Classes.FromAssemblyContaining<MessageHandler>()
.BasedOn(typeof(IDocumentHandler<>))
.WithService.Base()
.Configure(c => c.LifeStyle.Is(LifestyleType.Transient)),
Component.For<IDocumentHandlerFactory>()
.AsFactory(c => c.SelectedWith<ProcessorSelector>()));
單步調試代碼,攔截是調用,則執行finally從句(例如,我沒有得到方法名錯了)。然而,這個組件似乎沒有被釋放(使用性能計數器顯示了這一點,每次調用工廠的create方法都會增加一個計數器)。
到目前爲止,我的解決方法是向我的工廠接口添加一個void Release(IDocumentHandler處理程序)方法,然後在它執行handler.Process()方法之後,它明確釋放處理程序實例,做這項工作 - 性能計數器上升,並且處理完成後,它會下降)。
這裏是工廠:
public interface IDocumentHandlerFactory
{
IDocumentHandler GetHandlerForDocument(IDocument document);
void Release(IDocumentHandler handler);
}
這裏是我如何使用它:
IDocumentHandlerFactory handler = _documentHandlerFactory.GetHandlerForDocument(document);
handler.Process();
_documentHandlerFactory.Release(handler);
做發佈明確因此否定了攔截的需要,但我真正的問題是,爲什麼這個行爲在版本之間有所不同?
我有同樣的問題,如果它讓你感覺更好。 – CrazyCoderz
我有這樣的事情:Container.AddFacility(); Container.Register(Component.For ()。AsFactory()。LifestyleTransient()); // Documentation http://docs.castleproject.org/Windsor.Typed-Factory-Facility.ashx –
CrazyCoderz
接口如下所示:public interface IServiceFactory { T Create(); void發佈(object service); } –
CrazyCoderz