2012-01-19 17 views
3

這是與其他地方所述的類似的模式,並且詳述了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); 

做發佈明確因此否定了攔截的需要,但我真正的問題是,爲什麼這個行爲在版本之間有所不同?

回答

2

給自己的注意事項: - RTFM。或者事實上,閱讀Breakingchanges.txt文件。

下面是影響此行爲(重點是我的)變化: -

變化 - IReleasePolicy接口有一個新方法:IReleasePolicy CreateSubPolicy();子策略的使用改變了如何輸入工廠 手柄外的帶組件版本(見說明)

影響 - 中固定性 - 易

描述 - 這是加入作爲一種嘗試,以使更多的精粒度爲 生命週期範圍(主要針對現在的每種類型的工廠,但在未來的 中也會說客戶端應用程序中的每個窗口)。作爲 的副作用(和變化,以釋放上述策略行爲)它是沒有 不再能夠解除通過鍵入工廠解決對象,使用 container.Release。由於對象現在僅在工廠的範圍 中進行跟蹤,因此只有在致電工廠 釋放方法時或者工廠本身被釋放時纔會被釋放。

修復 - 方法應返回公開相同行爲 作爲「父」的新對象,通常最好是返回相同 類型的對象(如內置版本策略所做的那樣)。

我沒有找到修復建議在我的實例中非常有幫助,但是我的問題解決方案是你應該實際做的(使用工廠發佈)。如果其他人有這個(非)問題,我會放棄它。

+0

我有同樣的問題,如果它讓你感覺更好。 – CrazyCoderz

+0

我有這樣的事情:Container.AddFacility (); Container.Register(Component.For ()。AsFactory()。LifestyleTransient()); // Documentation http://docs.castleproject.org/Windsor.Typed-Factory-Facility.ashx – CrazyCoderz

+0

接口如下所示:public interface IServiceFactory { T Create (); void發佈(object service); } – CrazyCoderz

相關問題