10

我有一个界面:

public interface IService
{
    void DoStuff(int parm1, string parm2, Guid gimmeABreakItsAnExampleK);
}

我想配置 Ninject (v3) 绑定,以便我可以有一个“调度程序” shuffle 方法调用多个实例IService,如下所示:

public sealed class DispatcherService : IService
{
    private IEnumerable<IService> _children;

    public DispatcherService(IEnumerable<IService> children)
    {
        this._children = children.ToList();
    }

    public void DoStuff(int parm1, string parm2, Guid gimmeABreakItsAnExampleK)
    {
        foreach(var child in this._children)
        {
            child.DoStuff(parm1, parm2, gimmeABreakItsAnExampleK);
        }
    }
}

然而,我的绑定,看起来像这样,最终在运行时抛出一个异常,指示循环依赖:

this.Bind<IService>().To<DispatcherService>();

this.Bind<IService>().To<SomeOtherService>()
    .WhenInjectedExactlyInto<DispatcherService>();
this.Bind<IService>().To<YetAnotherService>()
    .WhenInjectedExactlyInto<DispatcherService>();

这可能吗?如果是这样,我做错了什么?忍者能否逃脱这种周期性依赖的厄运?

4

4 回答 4

2

如果您的调度程序是将IService 列表作为参数的唯一IService,那么这确实有效(我测试过):

kernel.Bind<IService>().To<DispatcherService>().When(x => x.IsUnique);
this.Bind<IService>().To<SomeOtherService>()
    .WhenInjectedExactlyInto<DispatcherService>();
this.Bind<IService>().To<YetAnotherService>()
    .WhenInjectedExactlyInto<DispatcherService>();

When子句适用于这种情况的原因是,当您的构造函数调用单个服务实例时,该IsUnique字段IRequest被设置为。true由于您DispatcherService需要一个IEnumerable,因此该值是false激活DispatcherService. 这可以防止循环依赖的发生。

实际上,告诉内核不要尝试将 DispatcherService 注入自身的任何正确方法都可以工作(这只是一个潜在有用的示例)。

编辑:简单地短路循环依赖的更明确的方法似乎是这样的:

kernel.Bind<IService>().To<DispatcherService>().When(
   request => request.Target.Member.DeclaringType != typeof (DispatcherService));
于 2012-10-16T03:36:21.943 回答
1

为什么不把DispatcherService中的IService去掉,取名为IDispatcherService,让被调用的服务(接收者)实现IService呢?

于 2012-10-15T15:39:50.263 回答
1

我必须承认我对 Ninject API 不是很熟悉,但我认为这样可以解决问题:

kernel.Bind<IService>().To<DispatcherService>();   

kernel.Bind<IEnumerable<IService>>().ToMethod(() => new IService[]
{
    kernel.Get<SomeOtherService>(),
    kernel.Get<YetAnotherService>(),
});
于 2012-10-11T21:39:28.263 回答
0

您可以通过将其中一个子集设置为命名绑定来将两个子集(调度程序或接收者)隔离开,然后使用名称作为将一个子集提供给另一个子集的一种方式(通过 aNamedAttribute或在您的接线中)

于 2012-10-12T09:22:29.993 回答