2010-07-08 54 views
0

考慮下面的類:Windsor如何爲每個解析調用創建一個組件?

public interface IView 
{ 
    /// <summary> 
    /// Ignore this (its only for the assertion) 
    /// </summary> 
    ITask Task { get; } 
} 

public class ViewA : IView 
{ 
    private readonly ITask _task; 

    public ViewA(ITask task) 
    { 
     _task = task; 
    } 

    public ITask Task 
    { 
     get { return _task; } 
    } 
} 
public class ViewB : IView 
{ 
    private readonly ITask _task; 

    public ViewB(ITask task) 
    { 
     _task = task; 
    } 

    public ITask Task 
    { 
     get { return _task; } 
    } 
} 

public class ViewManager 
{ 
    private readonly List<IView> _views; 

    public ViewManager(IView[] views) 
    { 
     _views = new List<IView>(views); 
    } 

    public ReadOnlyCollection<IView> Views 
    { 
     get { return new ReadOnlyCollection<IView>(_views); } 
    } 
} 

最後我試圖做到:

[Fact] 
    public void Configure_TwoServicesWithDependencyToTransientComponent_BothShareComponent() 
    { 
     // arrange 
     var windsorContainer = new WindsorContainer(); 

     windsorContainer.Kernel.Resolver.AddSubResolver(new ArrayResolver(windsorContainer.Kernel)); 

     windsorContainer.Register(Component.For<ITask>() 
      .ImplementedBy<TaskWithNoDependencies>() 
      .Named("task") 
      .LifeStyle.Transient); 

     windsorContainer.Register(Component.For<IView>().ImplementedBy<ViewA>().LifeStyle.Transient); 
     windsorContainer.Register(Component.For<IView>().ImplementedBy<ViewB>().LifeStyle.Transient); 

     windsorContainer.Register(Component.For<ViewManager>() 
      .LifeStyle.Transient); 

     // act 
     ViewManager service = windsorContainer.Resolve<ViewManager>(); 

     // assert 
     Assert.Same(service.Views[0].Task, service.Views[1].Task); 
    } 

我怎樣才能讓溫莎創建一個實例的ITask因此多數民衆贊成它由ViewA和ViewB解決時共享ViewManager?我嘗試以下,但它沒有工作:

 windsorContainer.Register(Component.For<ViewManager>() 
      .DynamicParameters((k, d) => 
            { 
             d["task"] = k.Resolve<ITask>(); 

            }) 
      .LifeStyle.Transient); 

回答

0

我找到了一個解決方案,但我希望有人可以建議更好的解決方案。請給我一些批評家所選擇的解決方案上:

[Fact] 
    public void Configure_TwoServicesWithDependencyToTransientComponent_BothShareComponent() 
    { 
     // arrange 
     var windsorContainer = new WindsorContainer(); 

     windsorContainer.Kernel.Resolver.AddSubResolver(new ArrayResolver(windsorContainer.Kernel)); 

     windsorContainer.Register(Component.For<ITask>().ImplementedBy<TaskWithNoDependencies>().LifeStyle.Custom(typeof(PerScopeOrTransientLifestyleManager))); 

     windsorContainer.Register(Component.For<IView>().ImplementedBy<ViewA>().LifeStyle.Transient); 
     windsorContainer.Register(Component.For<IView>().ImplementedBy<ViewB>().LifeStyle.Transient); 

     windsorContainer.Register(Component.For<ViewManager>() 
      .LifeStyle.Transient); 

     // act 
     ViewManager service; 

     using (new LifeStyleScope()) 
     { 
      service = windsorContainer.Resolve<ViewManager>(); 
     } 

     // assert 
     Assert.Same(service.Views[0].Task, service.Views[1].Task); 
    } 

我做了兩兩件事:

  1. 創建一個自定義的生活方式經理,其加入到說的組件將充當一種生活方式的瞬態之外的能力範圍和作爲一個單身。

  2. 創建一個生活方式範圍,我可以使用它來指定「上下文邊界」。

有一件事我不喜歡這個解決方案,那就是你必須知道來自呼叫站點的上下文問題。我可以通過將生活範圍轉移到視圖管理者來抽象,但是然後視圖管理者需要具有ioc依賴關係,這在測試視圖管理員時需要一些額外的瑕疵。

0
  1. 你爲什麼想要做這樣的嗎?你要做的是將一個實例綁定到依賴樹的上下文。或許上下文更廣泛,就像網絡請求一樣?你爲什麼想這樣做的原因是什麼?

  2. 這是可能的,但我知道乾淨的做法與溫莎2.5。以前的版本可能需要一些欺騙。

+0

這是一個winforms應用程序,我沒有任何靜態web請求上下文或任何東西來綁定它。上下文邊界通過解析「AnotherServiceWithTaskDependency」來定義。我可以訪問最新版本的Windsor,所以請告訴我乾淨的解決方案:-) – Marius 2010-07-08 17:19:53

+0

好吧,但爲什麼它是一個上下文邊界?你想在這兩個對象之間共享一個實例,而不是在其他對象之間共享一個實例的原因是什麼?它們之間的關係是什麼? – 2010-07-08 21:46:37

+0

我有一個「視圖管理器」,它將「視圖」列表作爲輸入參數。 「意見」必須分享一些組成部分,因爲他們必須對彼此之間的變化作出反應。兩個不同「ViewManagers」中的「視圖」不應共享前面提到的組件。因此解析「ViewManager」代表上下文邊界。基本上ViewManagers最終在不同的UI容器中。如果有幫助,我可以給你郵寄一些代碼。 – Marius 2010-07-09 05:49:10

相關問題