依赖注入是否扩大了可能是 "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
的主要作者
如果我要使用 DTO 跨 layers/assemblies 而不是持久性 classes 传递数据,我可以将对持久性模型中的 classes 的访问限制为内部对象同一个程序集。
但是在像 Orchard CMS 这样的系统中(它使用 NHibernate 进行 ORM,AutoFac 进行依赖注入),持久化是通过另一个组件提供的 IRepository<T>
进行持久化,系统将注入 IRepository<T>
到我在 class 构造函数之一的程序集,因此它需要持久的 class T 为 public。如果没有依赖注入,我可以将 T 定义为内部并在我的汇编代码中使用 IRepository<T>
,依赖注入是否要求 class 始终为 public?
是的,为了让容器能够实例化和提供依赖项,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
的主要作者