inversion-of-control - 为依赖注入(inject)设计类的指南

标签 inversion-of-control

关闭。这个问题是opinion-based .它目前不接受答案。












想改进这个问题?更新问题,以便 editing this post 可以用事实和引用来回答它.

3年前关闭。




Improve this question




This question about unit testing best practices提到为依赖注入(inject)设计类。这让我开始思考这究竟意味着什么。

刚刚开始使用控制容器的反转,我对这个问题有一些想法,所以让我把它们扔到墙上,看看有什么能坚持下去。

在我看来,一个对象可以拥有三种基本类型的依赖关系。

  • 对象依赖 - 相关类将使用的实际对象。例如 LogInFormController 中的 LogInVerifier。这些应该通过构造函数注入(inject)。如果该类的级别足够高以至于在构造函数中需要超过 4 个这些对象,请考虑将其分解或至少使用工厂模式。您还应该考虑为依赖项提供接口(interface)并针对该接口(interface)进行编码。
  • 一个简单的设置 - 例如阈值或超时时间。这些通常应该有一个默认值,并通过工厂模式的构建器进行设置。您还可以提供设置它们的构造函数重载。但是在大多数情况下,您可能不应该强制客户端必须明确设置它。
  • 消息对象 - 从一个类传递到另一个类的对象,接收类可能用于业务逻辑。一个示例是 LogInCompleRouter 类的用户对象。在这里,我发现最好不要在构造函数中指定消息,因为您必须在 IoC 容器中注册 User 实例(使其成为全局),或者在拥有 User 实例之前不实例化 LogInCompleteRouter (为此您不能使用 DI,或者至少需要对容器的显式依赖)。在这种情况下,最好仅在方法调用需要它时才传入消息对象(即 LoginInCompleteRouter.Route(User u); )。

  • 另外,我应该提一下,并不是所有的东西都应该 DI,如果你有一些简单的功能可以方便地分解到一次性类中,那么当场实例化可能是可以的。显然,这是一个判断电话;如果我发现编写一个类如
    class PasswordEqualsVerifier {
      public bool Check(string input, string actual) { return input===actual;}
    }
    

    我可能不会打扰依赖注入(inject)它,只会让一个对象直接在 using block 内实例化它。推论是,如果值得为其编写单元测试,那么它可能值得注入(inject)。

    那你们怎么看?欢迎任何额外的指导方针或对比意见。

    最佳答案

    重要的是尝试对接口(interface)进行编码,并让您的类接受这些接口(interface)的实例,而不是自己创建实例。你显然会为此发疯,但无论单元测试还是 DI,这都是一种普遍的好习惯。

    例如,如果您有一个数据访问对象,您可能倾向于为所有 DAO 编写一个基础,如下所示:

    public class BaseDAO
    {
        public BaseDAO(String connectionURL, 
                       String driverName, 
                       String username, String password)
        {
            // use them to create a connection via JDBC, e.g.
        }
    
        protected Connection getConnection() { return connection; }
    }
    

    但是,最好从类中删除它以支持接口(interface)
    public interface DatabaseConnection
    {
        Connection getConnection();
    }
    
    public class BaseDAO
    {
        public BaseDAO(DatabaseConnection dbConnection)
        {
            this.dbConnection = dbConnection;
        }
    
        protected Connection getConnection() { return dbConnection.getConnection(); }
    }
    

    现在,您可以提供 DatabaseConnection 的多个实现.即使忽略单元测试,如果我们假设我们正在使用 JDBC,有两种方法可以获得 Connection :来自容器的连接池,或直接通过使用驱动程序。现在,您的 DAO 代码未与任一策略耦合。

    对于测试,您可以制作 MockDatabaseConnection连接到带有固定数据的一些嵌入式 JDBC 实现以测试您的代码。

    关于inversion-of-control - 为依赖注入(inject)设计类的指南,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/127552/

    相关文章:

    c# - Simple Injector在BaseClass中注入(inject)多个依赖项

    asp.net-mvc-2 - 如何将 Ninject 与 ActionResults 结合使用,同时使 Controller 与 IoC 框架无关?

    inversion-of-control - NserviceBus 属性注入(inject)

    inversion-of-control - 超越世界/宇宙

    c# - 在 ASP.NET MVC 3 中在哪里初始化 ObjectFactory?

    c# - 当 Controller 类在不同的程序集中时,如何将 Controller 注册到 ASP.NET MVC 中?

    inversion-of-control - 温莎城堡 : How to programatically pass a list parameter to the container?

    c#-4.0 - 将同一接口(interface)的不同实现和配置注入(inject)到不同的客户端

    wpf - 如何使用 MVVMLight 初始化我的 WPF 应用程序?

    c# - 如何将此服务定位器模式转变为真正的依赖注入(inject)模式?