Ninject 2.0 - 绑定到多次使用相同接口的对象?

Fin*_*las 6 c# binding ninject ioc-container

考虑以下:

    public Something(IInterface concreteObjectOne, IInterface concreteObjectTwo) 
    {
        this.concreteObjectOne = concreteObjectOne;
        this.concreteObjectTwo = concreteObjectTwo;
    }
Run Code Online (Sandbox Code Playgroud)

如何设置此类绑定与Ninject?我试着用谷歌搜索这个词,但由于我不知道这叫做什么我不能,也无法在Wiki上找到任何关于此的内容.

编辑:

我相信,这就是所谓的以公约为基础的结合,如所描述这里.但是,此文档适用于版本1.0和2.0没有该Only方法.我希望这可以在没有属性的情况下实现 - 使用名称约定或类似的东西.

小智 9

除了使用"仅"方法之外,本文还通过为注入的对象指定不同的属性来提出另一种解决方案.

例:

public class ObjectOneAttribute : Attribute
{

}  
public class ObjectTwoAttribute : Attribute
{

}
Run Code Online (Sandbox Code Playgroud)

然后

public Something([ObjectOneAttribute] IInterface concreteObjectOne, [ObjectTwoAttribute] IInterface concreteObjectTwo) 
    {
        this.concreteObjectOne = concreteObjectOne;
        this.concreteObjectTwo = concreteObjectTwo;
    }
Run Code Online (Sandbox Code Playgroud)

当您想要将接口绑定到正确的具体对象时,请使用"WhereTargetHas"方法:

Bind<IInterface>().To<YourConcreteTypeOne>().WhereTargetHas<ObjectOneAttribute>();
Bind<IInterface>().To<YourConcreteTypeTwo>().WhereTargetHas<ObjectTwoAttribute>();
Run Code Online (Sandbox Code Playgroud)

更新:不使用属性的解决方案:
使用方法"When":

Bind<IInterface>().To<YourConcreteTypeOne>().When(r => r.Target.Name == "concreteObjectOne");  
Bind<IInterface>().To<YourConcreteTypeTwo>().When(r => r.Target.Name == "concreteObjectTwo")
Run Code Online (Sandbox Code Playgroud)

;


Mar*_*ann 5

如果我可以被允许提供一些通用的,而不是针对Ninject的指导,我会建议您稍微重新考虑您的设计.当前的构造函数是模糊的,因为它没有提供有关哪个IInterface实现的指导 - 我意识到这只是一个真实API的模型,而真正的API可能会为表单中的人类开发人员提供更多帮助对于恰当命名的参数,像DI Container这样的机器无法推断出正确的用法.

许多DI容器提供了一些解决这种模糊性的方法,例如通过提供可用于将名称(元数据)与每个依赖关联的属性.AFAIR,Ninject有Inject属性......

但是,请考虑以下几种选择:

第一种方法是将两个类似的接口实例封装在参数对象中,如下所示:

public interface IParameterObject
{
    IInterface ObjectOne { get; }

    IInterface ObjectTwo { get; }
}
Run Code Online (Sandbox Code Playgroud)

您现在可以更改构造函数以获取IParameterObject的实例,而不是两个接口实例本身.

public Something(IParameterObject po)
{
    this.concreteObjectOne = po.ObjectOne;
    this.concreteObjectTwo = po.ObjectTwo;
}
Run Code Online (Sandbox Code Playgroud)

这意味着您可以将IParameterObject的配置推送到Composition Root.

思考的另一个替代方案是将两个实例的情况考虑为一个更普遍的设计的特殊情况是否有意义,它需要任意数量的实例.这可能并非总是如此,但如果是,您可以将构造函数更改为:

public Something(IEnumerable<IInterface> objects)
Run Code Online (Sandbox Code Playgroud)

我个人更喜欢上述任何建议而不是任何使用特定Ninject功能的建议,因为它迫使我一般地使API更加明确,因此更具可读性和可维护性.