0

我目前正在使用 Ninject 处理 C#/.Net/MVC 应用程序上的 DI。当我跟踪服务实例的创建时,我发现服务在生命周期中被调用和构造的次数很多,因此我必须实例化服务并缓存它们,然后在实例化另一个服务之前检查缓存的服务。构造函数有时很重)。

对我来说这似乎很荒谬,因为服务不需要唯一的构造函数参数,因此对整个应用程序范围来说,实例化它们一次就足够了。

我作为一个快速替代方案所做的(现在只是为了概念验证,看看它是否有效)是......

  • 创建了一个静态类(称为 AppServices),其中包含我所有的服务接口作为它的属性。
  • 给定这个类一个 Init() 方法,该方法从我的服务库中实例化每个服务接口的直接实现。如果我使用 Ninject(或其他 DI 处理程序),这会模拟将它们绑定到内核。

例如

public static class AppServices(){
  public IMyService MyService;
  public IMyOtherService MyOtherService;

  public Init(){
     MyService = new MyLib.MyService();
     MyOtherService =  new MyLib.MyOtherService();
  }
}
  • 在 App_Start 上,我调用 Init() 方法来创建仅实例化一次的全局可访问服务列表。
  • 从那时起,每次我需要一个服务实例时,我都会从 AppServices 中获取它。这样我就不必继续构建我不需要的新实例。

例如

var IMyService _myService = AppServices.MyService;

这工作正常,我还没有出现任何问题。我的问题是这似乎太简单了。它只是几行代码,在应用程序范围内创建了一个静态类。因为它完全符合我需要 Ninject 做的事情,但是(在我看来,出于我的目的)一种更清洁和节省性能的方式,为什么我需要 Ninject?我的意思是,创建这些复杂的依赖注入处理程序是有原因的,对吧?我对 DI 的“简单”解释一定有问题,我就是看不到。

谁能告诉我为什么为我的服务实例创建一个全局静态容器是一个坏主意,也许可以准确解释是什么让 Ninject(或任何其他 DI 处理程序)如此必要。我了解 DI 的概念,所以请不要试图解释是什么让它如此出色。我知道。我想确切地知道它在幕后做了什么,这与我的 App_Start 方法如此不同。

谢谢

4

1 回答 1

1

你的问题需要分成两个问题:

  1. 使用单例模式而不是注入依赖项真的是错误的吗?
  2. 为什么需要 IoC 容器?

1)

不应该使用单例模式的原因有很多。以下是一些主要的:

可测试性

是的,您可以使用静态实例进行测试。但是你不能测试隔离(FIRST)。我已经看到一些项目搜索了很长时间为什么测试开始失败,但没有明显的原因,直到他们意识到这是由于测试以不同的顺序运行造成的。当你遇到这个问题时,你总是希望你的测试尽可能地隔离。静态值结合测试。

当您在单元测试之外还进行集成/规范测试时,情况会变得更糟。

可重用性

您不能简单地在其他项目中重复使用您的组件。其他项目也必须使用这个概念,即使他们可能决定使用 IoC 容器。

或者您无法创建具有不同依赖项的组件的另一个实例。组件依赖项将硬连接到 AppServices 中的实例。您将不得不更改组件实现以使用不同的依赖项。

2)做DI并不意味着你必须使用任何IoC容器。您可以实现自己的 IDependencyResolver 手动创建控制器并在需要的地方注入相同的服务实例。IoC 容器使用一些性能,但它们简化了对象树的创建。您将必须自己决定什么更重要,或者更简单地创建控制器。

于 2013-10-24T21:02:13.990 回答