【问题标题】:How Interface play role in Constructor Dependency Injection接口如何在构造函数依赖注入中发挥作用
【发布时间】:2019-02-28 06:23:38
【问题描述】:

我试图理解基于构造函数的依赖注入的概念。我已经看到了一些使用接口的constructor based dependency injection 的代码示例。在代码 sn-p 中,我看到服务类构造函数需要 interface 类型的参数,但是在创建服务类对象时,传递了实现该接口的类的实例。那么如何在运行时将类的类型转换为接口的类型,或者还有其他什么? 幕后发生了什么?

让我分享一些示例代码 -

界面-

要实现的简单接口

namespace constructor_di
{
    interface IRepoInterface
    {
        string test();
    }
}

存储库 -

Repository 类实现接口

namespace constructor_di
{
    class Repository : IRepoInterface
    {
        public string test()
        {
            return "Test String";
        }
    }
}

服务-

服务类期望在创建对象时传递IRepoInterface

namespace constructor_di
{
    class Service
    {
        private readonly IRepoInterface _repo;

        public Service(IRepoInterface repoInterface)
        {
            _repo = repoInterface;
        }
    }
}

程序启动 -

在这里创建服务类的实例

namespace constructor_di
{
    class Program
    {
        static void Main(string[] args)
        {
            Service obj = new Service(new Repository());
        }
    }
}

【问题讨论】:

  • 将对象实例作为参数传递给需要接口类型参数的方法是关于协方差(用更具体的类型代替一般类型),与 DI 无关.它的用途之一是在 DI 中,从某种意义上说,您可以让一个模拟对象实现相同的接口并传递它,而不是实际的对象。看看这里:devblogs.microsoft.com/csharpfaq/…

标签: c# oop dependency-injection


【解决方案1】:

通过构造函数进行依赖注入是减少紧密耦合和提高代码可测试性的好方法。你甚至不需要使用依赖注入容器;在您的组合根中,您指定将使用哪些实现这些接口的类并将它们注入到它们的使用者中。

具有表示为契约的依赖关系的类只关心契约指定的行为。它不关心实现细节。

这使您能够使用实现相同接口的装饰器来增强基本行为并添加额外的功能,而无需修改之前的 / 基本实现本身。

而且,在单元测试中,您可以使用某种模拟/假实现来隔离依赖关系,并更轻松地测试使用者本身。

关于你的问题:

那么如何在运行时将类的类型转换为接口的类型,或者还有其他什么?幕后发生了什么?

如果一个类实现了一个接口,它可以被注入到消费类中而无需任何转换。编译器确保您只与接口公开的成员进行交互。

延伸阅读:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/

【讨论】:

    【解决方案2】:

    接口是一个合同,其中定义了一些成员的签名。这与他们的实现无关。因此,任何实现该接口的类都在履行合同,因此它的对象是对该接口类型或实现该接口的类的类型检查的有效替代品。

    例子-

    using System;
    
    interface IRepoInterface
    {
        string test();
    }
    
    class BaseRepository : IRepoInterface
    {
        public string test()
        {
            return "Test String in implementing class";
        }
    }
    
    class ChildRepository : BaseRepository
    {
        public string SomeFunctionName()
        {
            return "Test String in child class";
        }
    }
    
    public class Program
    {
        public static void Main()
        {
            ChildRepository repo = new ChildRepository();
            Console.WriteLine(repo is ChildRepository);
            Console.WriteLine(repo is BaseRepository);
            Console.WriteLine(repo is IRepoInterface);
        }
    }
    
    

    在上面的代码sn-p中,类BaseRepository实现了接口,类ChildRepository扩展了类BaseRepository。

    因此 ChildRepository 类的任何对象都将通过 ChildRepository、BaseRepository 和 IRepoInterface 的类型检查。

    【讨论】:

      猜你喜欢
      • 2023-03-08
      • 2011-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多