依赖注入是否扩大了可能是 "internal" 的 class 的范围?

Does dependency injection enlarge the scope of a class which could be "internal"?

如果我要使用 DTO 跨 layers/assemblies 而不是持久性 classes 传递数据,我可以将对持久性模型中的 classes 的访问限制为内部对象同一个程序集。

但是在像 Orchard CMS 这样的系统中(它使用 NHibernate 进行 ORM,AutoFac 进行依赖注入),持久化是通过另一个组件提供的 IRepository<T> 进行持久化,系统将注入 IRepository<T>到我在 class 构造函数之一的程序集,因此它需要持久的 class T 为 public。如果没有依赖注入,我可以将 T 定义为内部并在我的汇编代码中使用 IRepository<T>,依赖注入是否要求 class 始终为 public?

是的,为了让容器能够实例化和提供依赖项,1 将可注入依赖项的范围扩展到 public .

事实上,依赖倒置原则的另一个常见(且被误导)"gripe" 是现在注入的所有 class 内部依赖通常暴露在 public 构造函数 - 似乎违反了 OO 的原始“3 Amigos”原则,它具有 class 的内部依赖性,牢牢隐藏在 public 视图之外。

权衡当然是通过 new 实例化将 class 直接耦合到其依赖项,这会阻止解耦,更糟糕的是,会妨碍测试,这在 post- SOLID 时代代码,被公认为第一个 class 设计问题。

要记住的一件事是,按照惯例,classes 之间的耦合应该总是通过接口 - 这样,实际上只有 "using" 这些 public classes 和构造函数将是容器本身,以及您的单元测试。

举例:

存储库程序集

public interface IFooRepo
{
     Task<IEnumerable<Foo>> FindFoos(Predicate predicate);
     // ...
}

// For IoC and testing purposes, MyFooRepo must be public
public class MyFooRepo : IFooRepo
{
    // .. Implement
}

服务组装

// Note : No indication of the IFooRepository dependency here
public interface IMyService
{
    Task DoAmazingThingsWithFoo();
}

// MyService class must also be public for IoC and tests
public class MyService : IMyService
{
     private readonly IMyRepo _repo;
     // Dependencies are publically visible on the constructor
     public MyService(IMyRepo repo)
     {
        _repo = repo;
     }
   // ... Implement
 }

IoC 引导

Bind<IFooRepo>().To<MyFooRepo>(); // Can also specify lifetimes etc
Bind<IMyService>().To<MyService>();

进一步阅读 - Mark Seemann 深入捍卫 public scope


[1] Steven 是 SimpleInject

的主要作者