问题 使用Ninject 2.0注入相同类型的多个构造函数参数


我正在使用Ninject 2.0在我的一个应用程序中处理DI,而且我遇到了令我困惑的事情。说实话,零文档并没有太大帮助。

假设我有一个带签名的构造函数 -

ctor(IServiceFactory factory1, IServiceFactory factory2)
{
    this.factory1 = factory1;
    this.factory2 = factory2;
}

虽然这两个服务实现了相同的接口,但它们是完全不同的实现,并且在不同的时间使用,因此我不想注入 IEnumerable<IServiceFactory>

我的问题是,当我绑定实例时,如何告诉Ninject为每个实例注入什么?

提前致谢。

更新

为了任何想要看到代码最终会在阅读了Remo的链接之后的人,...这里简单介绍一下。 (我从未意识到C#有参数属性!)

//abstract factory
public interface IServiceFactory
{
    Service Create();
}

//concrete factories
public class Service1Factory : IServiceFactory
{
    public IService Create()
    {
        return new Service1();
    }
}

public class Service2Factory : IServiceFactory
{
    public IService Create()
    {
        return new Service2();
    }
}

//Binding Module (in composition root)
public class ServiceFactoryModule : NinjectModule
{
    public override void Load()
    {
        Bind<IServiceFactory>()
            .To<Service1Factory>()
            .Named("Service1");

        Bind<IServiceFactory>()
            .To<Service2Factory>()
            .Named("Service2");
    }
}

//consumer of bindings
public class Consumer(
    [Named("Service1")] service1Factory,
    [Named("Service2")] service2Factory)
{
}

11748
2017-11-02 15:26


起源



答案:


首先,如果实现需要做一个完全不同的事情,你必须问自己,使用相同的接口是否正确。通常,接口是消费者和实现之间的契约。因此,如果消费者期望不同的东西,那么您可能会考虑定义不同的接口。

如果您决定使用相同的界面,则必须使用条件绑定。请参阅有关如何完成此操作的文档:

https://github.com/ninject/ninject/wiki/Contextual-Binding

https://github.com/ninject/ninject/wiki/Conventions-Based-Binding


10
2017-11-02 16:15



谢谢雷莫。它们实际上是抽象工厂的不同实现,它们在UI中创建Tabs,因此它们做同样的事情,......只是出于不同的原因。 - Stimul8d
我觉得你听不懂。从消费者的角度来看,他们并不是一回事。应从消费者的角度定义界面。例如。如果你有一个工厂界面 Fruit CreateFruit() 并且消费者期望两个实现一个用于香蕉,一个用于橙子,那么你应该更好地将接口定义为 Banana CreateBanana() 和 Orange CreateOrange() 即使你只需要它们作为水果。 - Remo Gloor
我懂了。您建议我使用工厂方法而不是具有混凝土工厂类的抽象工厂。这是一个选项,但工厂类本身具有需要注入的依赖项(在这种情况下为子屏幕)。具体的工厂和构造函数注入更容易解决这些依赖关系而不是工厂方法不是他们或者Ninject是否还有其他一些我不知道的魔法? - Stimul8d


答案:


首先,如果实现需要做一个完全不同的事情,你必须问自己,使用相同的接口是否正确。通常,接口是消费者和实现之间的契约。因此,如果消费者期望不同的东西,那么您可能会考虑定义不同的接口。

如果您决定使用相同的界面,则必须使用条件绑定。请参阅有关如何完成此操作的文档:

https://github.com/ninject/ninject/wiki/Contextual-Binding

https://github.com/ninject/ninject/wiki/Conventions-Based-Binding


10
2017-11-02 16:15



谢谢雷莫。它们实际上是抽象工厂的不同实现,它们在UI中创建Tabs,因此它们做同样的事情,......只是出于不同的原因。 - Stimul8d
我觉得你听不懂。从消费者的角度来看,他们并不是一回事。应从消费者的角度定义界面。例如。如果你有一个工厂界面 Fruit CreateFruit() 并且消费者期望两个实现一个用于香蕉,一个用于橙子,那么你应该更好地将接口定义为 Banana CreateBanana() 和 Orange CreateOrange() 即使你只需要它们作为水果。 - Remo Gloor
我懂了。您建议我使用工厂方法而不是具有混凝土工厂类的抽象工厂。这是一个选项,但工厂类本身具有需要注入的依赖项(在这种情况下为子屏幕)。具体的工厂和构造函数注入更容易解决这些依赖关系而不是工厂方法不是他们或者Ninject是否还有其他一些我不知道的魔法? - Stimul8d