0

我有一堆这样写的类:

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生活方式并使用自定义参数请求它们。我至少可以指定递归的最大允许深度吗?还是我错过了另一种方法?

另一个要求:我不能使用类型化工厂,因为我有很多不同类型的服务,因此不希望为这些服务单独生成许多工厂接口。

4

2 回答 2

1

容器没有注册任何 MyServiceXSettings 类型,因此获取服务的唯一方法是从容器中解析它,如下所示:

您还可以在组件注册期间使用专用的 SubResolver 或 DependsOn。

在构造函数中执行代码(而不是简单的变量赋值)是一种气味,使用容器更糟糕:它永远不应该在应用程序层泄漏。

乍一看,您似乎只是在使用设置来选择构造函数中的正确组件:这应该在 CompositionRoot 完成,使用 TypedFactory 或通过命名约定(您可能为同一个接口注册了多个组件,但是一个给定的参数名称驱动组件选择)

于 2013-09-30T13:43:07.687 回答
0

根据这个答案,我选择了懒惰的解决方案。

/// <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; }
    }
}
于 2013-10-07T20:42:46.853 回答