【问题标题】:Does dependency injection enlarge the scope of a class which could be "internal"?依赖注入是否扩大了可能是“内部”的类的范围?
【发布时间】:2018-05-12 18:30:44
【问题描述】:

如果我打算使用 DTO 跨层/程序集而不是持久类传递数据,我可以将对持久模型中的类的访问限制为同一程序集中的对象。

但是在像 Orchard CMS(使用 NHibernate 进行 ORM,AutoFac 进行依赖注入)这样的系统中,持久性是通过另一个提供 IRepository<T> 用于持久性的程序集,系统将在其中一个向我的程序集注入 IRepository<T>类构造函数,因此它需要持久类 T 是公共的。如果没有依赖注入,我可以将 T 定义为内部并在我的汇编代码中使用IRepository<T>,依赖注入是否需要该类一直是公共的?

【问题讨论】:

    标签: .net nhibernate dependency-injection orchardcms


    【解决方案1】:

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

    事实上,依赖倒置原则的另一个常见(并且被误导)“抱怨”是,现在注入的所有类的内部依赖项通常都暴露在公共构造函数上 - 似乎违反了原始的“3 Amigos 的 OO 原则,它具有一个类的内部依赖关系,它被牢牢地隐藏在公众视野之外。

    折衷当然是通过new 实例化直接将一个类与其依赖项耦合,这会阻止解耦,更糟糕的是,妨碍测试,这在后 SOLID 时代的代码中被认为是一流的设计问题.

    要记住的一点是,按照惯例,类之间的耦合应该始终通过接口进行 - 这样,真正“使用”这些公共类和构造函数的唯一参与者将是容器本身以及您的单元测试。

    举例:

    存储库组装

    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 的主要作者

    【讨论】:

    • 您指出“耦合通常应该针对接口”,虽然我的示例也针对接口,但接口本身绑定到公共类(IRepository),因此耦合是仍然反对类而不是接口,有没有更好的方法让我仍然可以只耦合到接口?
    • 我的意思是依赖于其他类的类只能通过接口(SOLID 的 D)耦合。 IoC 引导本身从来都不是一件优雅的事情——它通常会在需要接口依赖时定义要使用的具体类(一些 IoC 甚至会根据命名约定自动绑定)。我已经更新了一个示例 - 希望这可以澄清。
    猜你喜欢
    • 2017-03-20
    • 2017-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多