【问题标题】:I need some suggestion Dependency Injection in Constructor Injection method?我需要一些关于构造函数注入方法中的依赖注入的建议吗?
【发布时间】:2011-07-28 14:54:03
【问题描述】:

我对一些架构方法非常感兴趣。我喜欢DI和IOC,但是我不懂costructor注入;为什么这么复杂。我已经编写了下面使用构造函数注入的代码:

namespace DependencyInjection
{
    class Program
    {
        static void Main(string[] args)
        {
            ConstructorInjectionClass myCtx = new ConstructorInjectionClass(new PdfFormat());
            myCtx.Print();
            Console.Read();
        }
    }



    public interface IFormat
    {
        void Print();
    }

    public class PdfFormat : IFormat
    {

        public void Print()
        {
            Console.WriteLine("Pdf Format Print is completed...");
        }
    }


    // Constructor Injection

    public class ConstructorInjectionClass
    {
        private IFormat _format;

        public ConstructorInjectionClass(IFormat format)
        {
               _format = format;
        }

        public void Print()
        {
            _format.Print();
        }
    }

我在下面写了一些代码。我觉得很简单。



    public interface IFormat
    {
        void Print();
    }

    public class PdfFormat : IFormat
    {

        public void Print()
        {
            Console.WriteLine("Pdf Format Print is completed...");
        }
    }

   public interface ISave
    {
        void Add();
    }

    public class Sql: ISave
    {

        public void Add()
        {
            Console.WriteLine("Adding to SQL is completed...");
        }
    }


    // Constructor Injection

    public class ConstructorInjectionClass
    {


        public ConstructorInjectionClass(IFormat format)
        {
               format.Print();
        }

         public ConstructorInjectionClass(ISave saver)
        {
              saver.Add();
        }



为什么要使用构造函数注入?这两种方法的优缺点?

【问题讨论】:

  • 第二种方法的缺点是没有意义。我没有看到这两个构造函数的意义。
  • 我只看到一种方法?另一个是什么?

标签: c# .net oop design-patterns architecture


【解决方案1】:

第一个例子是构造函数注入。您正在将负责打印的类注入到类中。

在第二个示例中,您将使用 2 个参数之一创建一个新类,并在构造函数中使用该参数。这很糟糕有几个原因:

  • 您的构造函数实际上不应该做大量工作,这是在构造函数中保存或打印
  • 你不同的构造函数做不同的this。构造函数应该只创建你的类的一个新实例。
  • 目前尚不清楚不同的构造函数在被赋予不同的对象时实际上会做些什么。
  • 如果您将对象传递给构造函数,然后它只是调用它们,为什么不让构建此类的代码调用ISaveIPrint 实现上的方法。毕竟它必须有它们才能将它们传递给方法。如果您的对象在内部保存这些,那么它们可能在构造您的对象时提供(例如在您的组合根中),并且在您的对象上调用 Print 的客户端代码不需要知道任何关于 ISave 的事实并且存在IPrint 实现,

构造函数注入是关于你的类询问它在它的构造函数中的依赖关系,所以很清楚依赖关系是什么。通过要求依赖项而不是创建它们,测试类变得更简单,因为您可以注入模拟依赖项进行测试。

第一个选项很好,如果你想添加保存,那么你应该在构造函数中添加一个额外的参数来获取ISave 接口以及IPrint 接口并有一个方法Save委托给ISave 实现。

通过注入依赖项和对接口进行编程,以后可以更轻松地更改功能。例如,您可以轻松地将其保存到文件中(通过更改您传入的 IPrint 接口或通过更改您传递的 ISave 实现将其更改为保存到 xml 文件或 Web 服务。这使您类松散耦合到保存和打印实现

我会阅读 this 优秀答案以获得有关 DI/IOC 的更多指导

【讨论】:

  • +1 构造函数应该很简单:blog.ploeh.dk/2011/03/03/…
  • @Mark haha​​,只是添加了指向您出色答案的链接。虽然我与 Mark Seemann 没有任何关系,但我可以推荐他的 excellent book
【解决方案2】:

嗯,与任何模式一样,构造函数注入应该在且仅当使用它是一个好主意时才使用。您的示例代码有点奇怪...

  • 你的第一个例子是正确的。你的类有一个名为Print 的方法,它依赖于另一个类来进行打印。它不需要实例化此依赖项,而是要求在其构造函数中提供依赖项。这是Dependency Inversion Principle 的经典示例。基本上:“要求,不要实例化。”
  • 不过,您的第二个示例不太清楚。你的班级到底在做什么?这是为了什么?它有两个构造函数,它们对它们的依赖项执行操作,但是为什么呢?类中的其他任何地方都没有对这些类型的实例的依赖。那么为什么首先要有包装类呢?它似乎比你的第一个例子更......做作......目前尚不清楚代码的架构试图完成什么,因此它不是很好地使用构造函数注入。

【讨论】:

  • 你能用示例解释一下吗? “你的第一个例子是正确的。你的类有一个名为 Print 的方法,它依赖于另一个类来进行打印。它不需要实例化这个依赖项,而是要求在其构造函数中提供依赖项。这是一个经典的例子依赖倒置原则。基本上:“需要,不要实例化。”“
  • 我想:有什么奇怪的? “你的类有一个名为 Print 的方法,它依赖于另一个类来进行打印。”
  • @programmerist:嗯,一个例子是与几个数据库存储库交互的类。该类将具有一些具有大量业务逻辑的方法,并且基于该逻辑,通过几个存储库对数据库进行更改。您可以要求在构造类时提供它们的实例,而不是在内部实例化这些存储库。这可以由 IoC 框架(StructureMap 是我个人最喜欢的)或手动处理。就课程而言,两者都可以。
  • @programmerist:我不关注你的第二条评论。你在问什么?
  • @programmerist:你的第一个例子没有错。这是你的第二个例子,这很奇怪。您的第一个示例是通过构造函数注入进行依赖反转的经典示例。
【解决方案3】:

假设您想注入依赖项...您可以通过构造函数注入或属性设置器来执行此操作。我认为构造函数注入的优点之一是 IOC 使用这种策略。所以如果你不确定你想去 IOC 但你想做 DI 那么可能应该使用构造函数注入来使转换到 IOC 更容易......如果你改变主意......

【讨论】:

    猜你喜欢
    • 2016-10-16
    • 2011-02-02
    • 2018-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-20
    • 2021-08-14
    相关资源
    最近更新 更多