考虑以下课程:
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);
}
如何让Windsor创建一个ITask实例,以便在解析ViewManager时由ViewA和ViewB共享?我尝试了以下但是没有用:
windsorContainer.Register(Component.For<ViewManager>()
.DynamicParameters((k, d) =>
{
d["task"] = k.Resolve<ITask>();
})
.LifeStyle.Transient);
答案 0 :(得分:0)
你为什么要这样做?您要做的是将实例绑定到依赖关系树的上下文。也许上下文更广泛,就像网络请求一样?你想这样做的原因是什么。
有可能,但我知道使用Windsor 2.5这样做的干净方法。以前的版本可能需要一些技巧。
答案 1 :(得分: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);
}
我做了两件事:
创建了一个自定义的生活方式管理器,它增加了一种能力,即组件在生活方式范围之外作为瞬态,在单一范围内作为单身。
创建了一个生活方式范围,我可以用它来指定“上下文边界”。
有一件事我不喜欢这个解决方案,那就是你必须知道来自呼叫站点的上下文问题。我可以通过将生活方式范围移动到viewmanager来抽象这个,但是viewmanager需要有一个ioc依赖,在测试viewmanager时需要一些额外的存根。