2010-07-08 35 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

相关问题