2010-03-07 98 views
6

考虑以下几点:Ninject 2.0 - 绑定到多次使用相同接口的对象?

public Something(IInterface concreteObjectOne, IInterface concreteObjectTwo) 
    { 
     this.concreteObjectOne = concreteObjectOne; 
     this.concreteObjectTwo = concreteObjectTwo; 
    } 

如何设置设置此类型与Ninject结合起来?我试着用谷歌搜索这个词,但是因为我不确定这个名字叫什么,我也不知道,我也不能在维基上找到任何关于这个的东西。

编辑

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

回答

9

除了使用“唯一”方法,本文还通过为注入对象指定不同的属性来提出另一种解决方案。

例子:

public class ObjectOneAttribute : Attribute 
{ 

} 
public class ObjectTwoAttribute : Attribute 
{ 

} 

然后

public Something([ObjectOneAttribute] IInterface concreteObjectOne, [ObjectTwoAttribute] IInterface concreteObjectTwo) 
    { 
     this.concreteObjectOne = concreteObjectOne; 
     this.concreteObjectTwo = concreteObjectTwo; 
    } 

而当你想界面到正确的具体对象绑定,使用 “WhereTargetHas” 的方法:

Bind<IInterface>().To<YourConcreteTypeOne>().WhereTargetHas<ObjectOneAttribute>(); 
Bind<IInterface>().To<YourConcreteTypeTwo>().WhereTargetHas<ObjectTwoAttribute>(); 

更新:解不使用属性:
使用方法 “当”:

Bind<IInterface>().To<YourConcreteTypeOne>().When(r => r.Target.Name == "concreteObjectOne"); 
Bind<IInterface>().To<YourConcreteTypeTwo>().When(r => r.Target.Name == "concreteObjectTwo") 

;

+0

我宁可不添加属性。文章结尾展示了如何利用惯例,例如该参数被命名为X.这就是我真正想要的。 – Finglas 2010-03-07 13:25:57

+0

@Finglas我更新了另一个解决方案 – 2010-03-07 13:31:10

+0

这很棒。当我在玩弄这个工作时,我很接近,但是你很清楚。顺便说一下,我没有任何反对属性的东西,在这种情况下我发现它很浪费。这种类型的配置在我的代码库中并不常见,所以使用When方法更好。干杯。 – Finglas 2010-03-07 13:37:38

5

如果我可能被允许提供一些通用的,而不是Ninject特定的指导,我建议你稍微重新考虑你的设计。目前的构造函数是含糊,因为它没有提供关于IInterface的哪个实现在哪里的指导 - 我意识到这仅仅是您真实API的模型,而真正的API可能会为开发人员提供更多帮助恰当命名参数的形式,像DI容器这样的机器无法推断正确的用法。

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

然而,考虑几个选择:

第一个选择是封装在两个类似的接口实例在参数对象,像这样:

public interface IParameterObject 
{ 
    IInterface ObjectOne { get; } 

    IInterface ObjectTwo { get; } 
} 

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

public Something(IParameterObject po) 
{ 
    this.concreteObjectOne = po.ObjectOne; 
    this.concreteObjectTwo = po.ObjectTwo; 
} 

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

另一种方法去思考是,是否是有意义的考虑两个实例只是一个特殊情况更普遍的设计,采用实例的任何数量的的情况。这可能并非总是如此,但如果是这样,你可以改变构造这样:

public Something(IEnumerable<IInterface> objects) 

我个人喜欢的任何的上述建议在使用特定Ninject功能什么,因为它迫使我通常使API更明确,从而更易于读取和维护。

+0

@Mark。您昨天回答(再次感谢)让我使用工厂,以便为我的可插入算法使用策略设计模式。有问题的工厂现在采用两个具体对象,但由于我使用的是战略模式,它们都是相同的界面。通常没有IOC,我会编写这样的代码并手动连接依赖关系。它也使得单元测试变得容易。虽然你的建议可以起作用,但我总觉得它是有用的。对于2.0,我似乎无法找到正确的方式做任何事情,只是简单的绑定。 – Finglas 2010-03-07 13:24:21

+0

够公平 - 很高兴你找到了解决方案:) – 2010-03-07 14:10:21

相关问题