代码之家  ›  专栏  ›  技术社区  ›  4thSpace wkw

仅使用基类的依赖注入示例

  •  0
  • 4thSpace wkw  · 技术社区  · 15 年前

    不需要任何第三方工具就可以进行DI吗?在人们发现一些di框架之前,我已经读过一些关于使用抽象类和接口的文章。身份证是如何以这种最基本的形式完成的?

    5 回复  |  直到 15 年前
        1
  •  4
  •   Esko Luontola    15 年前

    实例化类时,只需将依赖项传递给类的构造函数。当项目很小(少于几千行代码)时,不需要DI框架——您可以编写工厂并手动连接所有依赖项。

        2
  •  2
  •   Fredrik Mörk    15 年前

    当然,没有第三方工具是可能的。简单示例:

    interface ILogger
    {
        void Log(string text);
    }
    
    class SomeClass
    {
        private ILogger _logger;
        public SomeClass(ILogger logger)
        {
            _logger = logger;
        }
    
        public void DoSomeWork()
        {
            Log("Starting");
            // do work
    
            Log("Done");
        }
    
        private void Log(string text)
        {
            if (_logger != null)
            {
                _logger.Log(text);
            }
        }
    }
    

    SomeClass 采取一个 ILogger 作为构造函数中的输入。它用来记录一些输出。假设我们希望它在控制台中:

    class ConsoleLogger : ILogger
    {
        public void Log(string text)
        {
            Console.WriteLine(text);
        }
    }
    

    在某些代码中:

    SomeClass instance = new SomeClass(new ConsoleLogger());
    instance.DoSomeWork();
    

    …但是我们希望登录到一个文件中:

    class FileLogger : ILogger
    {
        private string _fileName;
        public FileLogger(string fileName)
        {
            _fileName = fileName;
        }
    
        public void Log(string text)
        {
            File.AppendAllText(_fileName, text);
        }
    }
    

    因此,我们注入文件记录器:

    SomeClass instance = new SomeClass(new FileLogger("path to file"));
    instance.DoSomeWork();
    

    身体类 很高兴没有意识到 逃避者 正在使用的实现,只使用注入的任何实现。通常,让工厂创建接口实现的实例,而不是让对象在代码中到处构造是一个好主意,这样可以更简单地更改正在使用的实现。

        3
  •  2
  •   Tomas Aschan    15 年前

    里面有很好的描述 this tutorial .

    基本上你所做的就是 DependingClass 只知道 Interface ,然后使用 IndependentClass . 使用构造函数重载,例如,可以让单元测试框架发送模拟对象。
    一些代码可能更容易理解我的意思:

    public interface IAnInterface
    {
        void MethodOne();
        void MethodTwo();
    }
    
    public class IndependentClass : IAnInterface
    {
         // Implements all members of IAnInterface
    }
    
    public class DependentClass
    {
        private IAnInterface _dependency;
    
        public DependentClass() : this(new IndependentClass()) { }
    
        public DependentClass(IAnInterface dependency)
        {
            this._dependency = dependency;
        }
    }
    

    现在,如您所见,我们提供了一个默认的类类型,如果没有向构造函数提供任何参数,该类类型将被实例化。但我们也允许 注射 实现相同接口的不同类,或相同的模拟对象。

    编辑:正如评论中指出的,在一个较大的应用程序中,最好有一个工厂来实例化 依赖类 ,并移除“默认”构造函数。这样,如果您决定更改实现,您只需在一个地方进行更改。

        4
  •  0
  •   Claudiu Mihaila    15 年前

    您可以创建通过接口相互通信的组件,并让宿主程序实例化组件并将它们链接在一起。

    这将是您的解决方案结构:

    • 定义组件(接口+作为接口方法签名一部分的数据对象)之间的协定的dll程序集。

    • 一个或多个定义组件(实现接口)的dll程序集。组件之间的任何通信都是通过接口完成的。

    • 启动宿主进程、实例化组件并链接它们以设置某些属性的exe程序集。每当需要替换一个组件时,只需更改此项目。

    您可以为任何组件创建单元测试,模拟您正在测试的组件所使用的组件。

    此外,您还可以从宿主项目中的app.confing文件读取属性绑定。

        5
  •  0
  •   Charles Bretana    15 年前

    有三种方法可以做到…

    1. 将引用传递给构造函数中的依赖实例(它是实现接口的类的实例)。

      public class MyClass
      {
          private readonly ISpillDAL iSpDal;
          public ISpillDAL SpillDal { get { return iSpDal; } }
          public SpillLogic() : this(null) { }
          public SpillLogic(ISpillDAL splDAL)
          {
             iSpDal = splDAL ?? new SpillDAL();  // this allows a default 
          }
      }
      
    2. 创建新对象并 然后 通过属性设置器传递对从属对象的引用

      public class MyClass 
      { 
         private readonly ISpillDAL iSpDal; 
         public ISpillDAL SpillDal    
         { 
            set { iSpDal = value; } 
            get { return iSpDal; } 
         }
         public SpillLogic() { }        
      }
      
    3. 在对象中使用接受引用并将其分配给为此创建的内部provbate变量的函数

      public class MyClass 
      { 
         private readonly ISpillDAL iSpDal; 
         public ISpillDAL SpillDal    
         { 
            set { iSpDal = value; } 
            get { return iSpDal; } 
         }
         public SpillLogic() { }    
         public void InjectSpillDAL(  ISpillDAL splDAL )
         {  iSpDal = splDAL; } 
      }