2011-11-08 29 views
3

我正在使用Castle Windsor的子容器功能來覆蓋在工廠方法中使用特定實例註冊特定類型。我純粹使用子容器,以便註冊對於單個解決方案是臨時的 - 換句話說,我不希望註冊影響該類型的所有解決方案。使用Castle Windsor子容器來解析具有特定實例的類型

也許有些代碼會解釋我的意思。

我有一個充當工廠的Func Func<IReportCategory, IReportCategoryViewModel> - 我給它一個IReportCategory的實現,它返回一個IReportCategoryViewModel的新實例。 (IReportCategoryViewModel依賴於IReportCategory)。

 container.Register(
      Component.For<Func<IReportCategory, IReportCategoryViewModel>>().Instance(
       category => ResolveCategoryViewModelFactory(container, category))); 

ResolveCategoryViewModelFactory是實現如下:

private CategoryViewModel ResolveCategoryViewModelFactory(IWindsorContainer container, IReportCategory category) 
    { 
     using (IWindsorContainer childContainer = new WindsorContainer()) 
     { 
      childContainer.Register(Component.For<IReportCategory>().Instance(category)); 
      container.AddChildContainer(childContainer); 

      return childContainer.Resolve<IReportCategoryViewModel>(); 
     } 
    } 

什麼上面的方法實現是IReportCategoryViewModel的分辨率,注入的具體實例

這與溫莎城堡如下注冊IReportCategory作爲依賴項。如果IReportCategoryViewModel具有其他需要滿足的依賴關係,那麼這些將被容器自動注入。

隨後,我可以使用函數功能如下:

public class Test 
{ 
    private readonly Func<IReportCategory, IReportCategoryViewModel> factory; 

    public Test(Func<IReportCategory, IReportCategoryViewModel> factory) 
    { 
     this.factory = factory; 
    } 

    public void ResolveTest() 
    { 
     // Create a category (note: this would probably be resolved from the container in some way) 
     IReportCategory category = new ReportCategory(); 

     // Call into the factory to resolve the view model 
     IReportCategoryViewModel vm = factory(category); 
    } 
    ... 

問:這是否看起來像一個合適的事是什麼?從我得到的印象來看,Castle Windsor不推薦使用兒童容器 - 是否有另一種達到相同結果的方式?

感謝您的幫助。

回答

2

絕對有更好的方法去,你現在使用的代碼有一個錯誤 - 它會嘗試釋放你處理子容器時解決的所有組件實例,因此它們可能是在您甚至有機會使用它們之前無法使用(處置)。

如果我正確理解你的解釋,那感覺就像是typed factories的工作。

+0

鍵入工廠確實是一個更好的方式來做到這一點!非常感謝Krzysztof! –

+2

這並不完全導致與子容器相同的行爲 - 因爲它使用名稱將構造函數參數與工廠方法參數相匹配,它僅適用於工廠本身返回的類型,這意味着它的任何依賴項都不會「如果它們需要注入,則將實例傳遞給工廠方法。以下是我一直在探索的一個要點(這可能更好地解釋:))https://gist.github.com/1357829 – GraemeF

4

遵循Krzysztof建議使用Typed Factories,以下是我如何實現上述功能。這比使用兒童容器要簡單得多!

首先,創建一個工廠接口定義了工廠方法的簽名:

public interface ICategoryViewModelFactory 
{ 
    CategoryViewModel Create(ReportCategory category); 
} 

接着,確保TypedFactoryFacility在容器被使能:

container.AddFacility<TypedFactoryFacility>(); 

最後,寄存器工廠接口與容器:

container.Register(
    Component.For<ICategoryViewModelFactory>() 
     .AsFactory()); 

現在你可以在JECT ICategoryViewModelFactory到你的類,並調用Create()方法來創建的CategoryViewModel一個新實例:

public class SomeClass 
{ 
    public SomeClass(ICategoryViewModelFactory categoryViewModelFactory) 
    { 
     // This would probably be resolved by the container (it's like this for the example) 
     ReportCategory category = new ReportCategory(); 

     // Get Windsor to resolve the view model using the factory 
     ReportCategoryViewModel vm = categoryViewModelFactory.Create(category); 

     .... 

警告:在工廠方法的參數名稱需要的對象的構造函數的參數名稱匹配工廠創建。在上述例子中,工廠接口定義了方法:

CategoryViewModel Create(ReportCategory category) 

CategoryViewModel的構造還必須具有參數命名爲「類別」:

public CategoryViewModel(ReportCategory category) 

這是因爲工廠方法是相當於如下:

container.Resolve<CategoryViewModel>(new { category = paramPassedIntoFactoryMethod }); 
+0

感謝您發佈用於解決此問題的代碼 - 我花了很長時間尋找一個像這樣的例子來幫助我。不過,我仍然堅持,希望你能幫助。我已經有效地複製了您的代碼並替換了幾個字以使其適合於我的對象,並且在運行該應用程序時,我得到了一個「DependencyResolverException」,與我的「ReportCategory」對象相當。該例外狀態表明我的視圖模型依賴於無法解析的模型。你有沒有在溫莎城堡註冊過ReportCatgory?如果是這樣,怎麼樣? – Stu

+0

我設法得到這個工作,併發布了我的代碼在以下問題:http://stackoverflow.com/a/11604109/336752 – Stu

相關問題