2

前言

我觉得在使用 DI 框架时确实有可能让自己陷入困境。
(我选择的框架是 ninject,所以我将在我的示例中使用它。)

我将退后一步,看看 DI框架存在的原因:
为了防止不得不手动进行 DI

没错,本着 Ninjects 文档的精神,假设我们有一个Dojo创建Samurais 的对象。这些Samurais 是IWeapon在制作时给出的。

class Samurai{
    readonly IWeapon weapon;

    public Samurai(IWeapon weapon){
        this.weapon = weapon;
    }
}

现在我的理解是DojoKernel.Get<IWeapon>()创建Samurai.


,我不是只是将我的 Dojo 与内核耦合了吗?
另外...应该如何获得内核:DI,单例,服务位置?

我觉得我们很快就打破了 DI 的目的,因为现在我依赖于我的 DI 框架。如果忍者被击败并且忍者也死了会发生什么?

问题

我们如何在不耦合到 DI 框架的情况下使用 DI?

邮报

我确定以前有人问过这个问题,但是我找不到任何东西。请使用评论发布相关问题,以便我们可以汇集知识以找出最佳解决方案。

4

3 回答 3

5

在进行依赖注入时,诀窍是让所有类通过构造函数注入它们的依赖项。这样,您可以让内核从根对象为您构建一个完整的对象图。

然而,这个“根对象”必须通过调用直接解决kernel.Get<HomeController>()(如果HomeController是根对象)。因此,您必须在应用程序的某个地方调用kernel.Get. 没有是不可能的。

诀窍是将其最小化为应用程序中理想的单行代码,并将其放置在启动路径附近。可能靠近您注册依赖项的地方。应用程序的其余部分忽略了任何 DI 框架的使用。

甚至还有用于 Ninject 和其他容器的集成包,允许您根据使用的应用程序平台删除单行代码。例如,ASP.NET MVC 具有很好的扩展点,允许您插入一个ControllerFactory允许您让该工厂kernel.Get为您调用的点。

我们如何在不耦合到 DI 框架的情况下使用 DI?

总会有一些耦合,但理想情况下,这应该只是启动路径。所有其他代码都应该忽略容器的使用。仍然会有一个程序集依赖,但这个依赖只会存在于启动项目中,而不存在于您的业务层中。

查看 DI 框架存在的原因:防止不得不手动进行 DI

更准确地说。DI 有助于使您的应用程序更易于维护。DI 框架有助于使您的应用程序(又名组合根)的启动路径更易于维护。

于 2012-12-18T12:21:26.770 回答
2

实际上 Service Locator 设计模式被认为是有害的(实际上从许多角度来看被认为是反模式),所以我强烈反对在你的代码中使用它。

使用服务定位器会导致您的类 ( class Dojo) 与其客户之间的接口不明确。阅读你的类头将不可能理解所需的上下文:我应该怎么做才能正确使用这个类:我应该在什么里面放什么来满足所有的要求。

实际上,我更喜欢使用另一种称为Composition Root的模式,当我们仅在应用程序的一个位置使用容器(又名服务定位器)时:在应用程序的根目录中,例如MainHomeController

我强烈建议看一下有关该主题的书: Mark Seeman的“.NET 中的依赖注入”,它更详细地涵盖了所有这些主题。

于 2012-12-18T12:51:00.527 回答
1

您还可以对 DI 容器进行某种抽象。考虑这样的界面,

public interface IDependencyResolver
{
    T Get<T>();
}

然后你有一个实现 - 对于 Ninject 它可能看起来像这样。

public class NinjectDependencyResolver : IDependencyResolver
{
    private readonly IKernel _kernel = new StandardKernel();

    public T Get<T>()
    {
        return _kernel.Get<T>();
    }
}

这意味着您可以像使用项目中的任何其他 3rd 方组件一样使用 Ninject,但读取的行除外

IDependencyResolver resolver = new NinjectDependencyResolver();

根据您的需要,只能在某个地方找到一次。然后,您使用您的IDependencyResolver实例而不是IKernelNinject 提供的实例(或其他框架的类似容器)。

切换 DI 容器只需实现一个新的IDependencyResolver.

于 2012-12-18T12:25:10.017 回答