c# - 具有非接口(interface)的构造函数参数的依赖注入(inject)

标签 c# dependency-injection ninject

我仍然是 DI 的新手,我正在尝试了解我是否以错误的方式思考问题。当我想表示一个依赖于 IRandomProvider 的 Die 对象时,我正在处理一个玩具问题。该界面很简单:

public interface IRandomProvider 
{
   int GetRandom(int lower, int upper);
}

我想要一个看起来像这样的 Die 构造函数:

Die(int numSides, IRandomProvider provider)

我正在尝试使用具有如下方法的静态 DIFactory:

    public static T Resolve<T>()
    {
        if (kernel == null)
        {
            CreateKernel();
        }
        return kernel.Get<T>();
    }

其中 CreateKernel 仅绑定(bind)到 IRandomProvider 的特定实现。

我希望能够调用它:

DIFactory.Resolve<Die>(20);

如果不制作一个特殊版本的“Resolve”,我就无法完成这项工作,它可以让我处理 ConstructorArgs。这似乎让事情变得过于复杂,并且需要我为它的每个其他实例修改 DIFactory,以及绑定(bind)到构造函数参数的特定名称。

如果我重构 Die 类以不使用 int 构造函数,则一切正常。但是现在有人必须记住初始化 numSides 参数,这似乎是个坏主意,因为这是该类的要求。

我怀疑这对 DI 来说是一个糟糕的心智模型。谁能赐教一下?

最佳答案

控制反转容器不是工厂。不要使用它来解析像 Die 类这样的业务对象。控制反转是一种模式,用于让容器控制对象的生命周期。这样做的好处是它还支持依赖注入(inject)模式。

通常会创建、更改和处置业务对象。因此不需要为他们使用容器。正如您刚刚注意到的,它们确实在构造函数中采用了强制参数,这使得它们很难使用容器。

可以在容器中注册一个DieFactory,让它在构造函数中取IRandomProvider:

public class DieFactory
{
    public DieFactory(IRandomProvider provider)
    {}

    public Die Create(int numberOfSides)
    {
        return new Die(numberOfSides, _provider);
    }
}

但是创建一个用于创建所有相关业务对象的工厂当然会更好。然后你可以将内核作为依赖:

public class AGoodNameFactory
{
    public DieFactory(IKernel kernel)
    {}

    public Die CreateDie(int numberOfSides)
    {
        var provider = _kernel.Resolve<IRandomProvider>();
        return new Die(numberOfSides, provider);
    }

    // other factories.
}

或者您可以直接将 IRandomProvider 作为创建 Die 类的类中的依赖项。

关于c# - 具有非接口(interface)的构造函数参数的依赖注入(inject),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12136926/

相关文章:

c# - 无法向 Google 电子表格添加行

c# - Invalid token '=' in class, struct, or interface member declaration, Invalid token '(' in class, struct, or interface 成员声明

dependency-injection - 库项目中构造函数参数的默认值

c# - 使用 owin 和 ninject 的 webapi 应用程序中的无参数构造函数问题

asp.net-mvc - Ninject 停止注入(inject)我的属性

c# - 使用 Caliburn.Micro 同时显示两个 WPF 窗口

c# - Process.start 在网络驱动器上,要求身份验证

c# - 将 TimeSpan 解析或转换为字符串

c# - 在 DI 注入(inject)容器中注册受约束的 MediatR 管道行为

javascript - 无法将依赖项注入(inject)到派生类中