接口如何在构造函数依赖注入中发挥作用

时间:2019-02-28 06:23:38

标签: c# oop dependency-injection

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

让我分享一些示例代码-

接口-

要实现的简单界面

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

存储库-

存储库类实现接口

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;
        }
    }
}

程序启动-

在此处创建Service类的实例

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

2 个答案:

答案 0 :(得分:2)

通过构造函数进行依赖注入是一种最小化紧密耦合并提高代码可测试性的好方法。您甚至不需要使用依赖项注入容器。在您的组合根目录中,指定要使用哪些实现这些接口的类,并将其注入其使用者。

具有依赖关系表示为合同的类,则仅关心合同指定的行为。它不在乎实现细节。

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

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

关于您的问题:

  

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

如果一个类实现了一个接口,则可以将其注入到使用中的类中,而无需任何强制转换。编译器确保您仅与接口公开的成员进行交互。

进一步阅读:https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/

答案 1 :(得分:1)

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

示例-

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);
    }
}

在上面的代码片段中,BaseRepository类实现了Interface,而ChildRepository类扩展了BaseRepository类。

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