我有一堆像这样编写的课程:
public class MyService1 {
public MyService1(MyService1Settings settings, <service-dependent list of dependencies filled by Windsor>) { ... }
}
在温莎注册如下:
container.Register(
...
Component.For<MyService1>().LifestyleTransient(),
Component.For<MyService2>().LifestyleTransient(),
...
);
容器没有注册任何MyServiceXSettings
类型,因此获取服务的唯一方法是从容器中解析它,如下所示:
TService service = windsorContainer.Resolve<TService>(new { settings });
问题是,根据settings
对象中的参数,其中一个服务尝试使用不同的设置对象获取其类型的另一个实例。
有些事情:
public class MyService2 {
public MyService2(MyService2Settings settings, <service-dependent list of dependencies filled by Windsor>)
{
this.uplink = settings.Counter == 1
? new AnotherUplink()
: new RecursiveUplink(
container.Resolve<MyService2>(new {
settings = new MyService2Settings(settings.Counter - 1)
});
}
}
这个递归依赖链是有限的(并且大约有6个实例),但是当第一个服务尝试获取另一个服务时,Windsor会抛出异常,说明它是循环依赖。
我已将所有服务宣传为具有Transient
生活方式并使用自定义参数请求它们。我至少可以指定递归的最大允许深度吗?或者我错过了另一种我可以做到的方式?
另一个要求:我不能使用类型化的工厂,因为我有很多不同类型的服务,所以不希望为这些服务单独生成许多工厂接口。
答案 0 :(得分:1)
容器没有注册任何MyServiceXSettings类型, 所以获得服务的唯一方法是从容器中解决它 这样:
您也可以在组件注册期间使用专用的SubResolver或DependsOn。
在构造函数中执行代码(而不是简单的变量赋值)是一种气味,即使使用容器也是最糟糕的:它应该永远不会在应用程序层中泄漏。
乍一看,似乎您只使用设置在构造函数中选择正确的组件:应该在CompositionRoot中使用TypedFactory或naming convention完成(您可能已注册了多个组件)对于相同的intercace,但给定的参数名称驱动组件选择)
答案 1 :(得分:0)
根据this answer,我选择了懒惰的分辨率。
/// <summary>
/// Represents single component instance producer.
/// </summary>
/// <typeparam name="TComponent">type of the component to create</typeparam>
public interface IComponentCreator<TComponent>
{
/// <summary>
/// Gets the created component.
/// </summary>
TComponent Component { get; }
}
/// <summary>
/// Creates the component only when it's first requested.
/// </summary>
/// <typeparam name="TComponent">type of the component to create</typeparam>
public class LazyCreator<TComponent> : IComponentCreator<TComponent>
{
private readonly Func<TComponent> creatingFunction;
private bool created;
private TComponent component;
public LazyCreator(Func<TComponent> creatingFunction)
{
this.creatingFunction = creatingFunction;
}
public TComponent Component
{
get
{
if (!created)
{
component = creatingFunction();
created = true;
}
return component;
}
}
}
/// <summary>
/// Returns already created component.
/// </summary>
/// <typeparam name="TComponent">type of the component</typeparam>
public class ComponentContainer<TComponent> : IComponentCreator<TComponent>
{
private readonly TComponent component;
public ComponentContainer(TComponent component)
{
this.component = component;
}
public TComponent Component
{
get { return component; }
}
}