【问题标题】:Why does it seem like this interface provides implementation?为什么看起来这个接口提供了实现?
【发布时间】:2023-03-09 08:53:01
【问题描述】:

我按照教程使用 EF Core 构建了一个后端并实现了存储库模式。

首先,我创建了一个存储库接口和一个提供基本 CRUD 方法的存储库基类。然后,我为我需要与这些特定类上的数据交互的任何自定义方法为我的每个实体创建了单独的接口和存储库。

其次,我创建了一个接口和一个名为 IRepositoryWrapper 和 RepositoryWrapper 的具体类。定义要返回的存储库和保存方法,然后是检索存储库的实现和保存更改方法。

最后,我创建了一个控制器并将 IRepositoryWrapper 注入到控制器的构造函数中。

我的问题是:为什么将接口注入控制器实际上有效?既然接口只提供了定义,为什么实际的实现似乎也随之而来呢?我觉得我应该注入具体的 RepositoryWrapper 类。

https://code-maze.com/net-core-web-development-part4/#repository

这可以正常工作,我只是在问一个 OOP 问题。

public interface IRepositoryWrapper
{
    IScenarioRepository Scenario { get; }
    IConditionRepository Condition { get; }

    void Save();
}

public class RepositoryWrapper : IRepositoryWrapper
{
    private EvaluatorContext _evaluatorContext;
    private IConditionRepository _condition;
    private IScenarioRepository _scenario;

    public RepositoryWrapper(EvaluatorContext evaluatorContext)
    {
        this._evaluatorContext = evaluatorContext;
    }

    public IScenarioRepository Scenario
    {
        get
        {
            if (_scenario == null)
            {
                _scenario = new ScenarioRepository(_evaluatorContext);
            }

            return _scenario;
        }
    }

    public IConditionRepository Condition
    {
        get
        {
            if (_condition == null)
            {
                _condition = new ConditionRepository(_evaluatorContext);
            }

            return _condition;
        }
    }

    public void Save()
    {
        _evaluatorContext.SaveChanges();
    }
}

控制器类:


[Route("api/[controller]")]
[ApiController]
public class ScenariosController : ControllerBase
    {

        private IRepositoryWrapper _repositoryWrapper;

        //What I am calling injecting this interface into the constructor
        public ScenariosController(IRepositoryWrapper repositoryWrapper)
        {
            this._repositoryWrapper = repositoryWrapper;
        }

        [HttpGet]
        public IEnumerable<Scenario> FindAll()
        {

            return this._repositoryWrapper.Scenario.FindAllWithIncludes();
        }

    }

【问题讨论】:

  • 当你说,“为什么将接口注入到控制器中实际上起作用了?”,你指的是哪一行代码?
  • @RufusL 我编辑了这篇文章。我添加了控制器类和一个注释,描述了它在我看来就像一个接口被注入的位置。本来应该这样做的。
  • 因为您在容器中注册了RepositoryWrapper(针对界面)。容器根据定义不能只给你一个实例IRepositoryWrapper(自己试试这个 - 试试new up IRepositoryWrapper)。没有办法实例化一个接口。它需要实例化实现接口的东西。
  • I feel like I should be injecting the concrete class RepositoryWrapper instead. 当然你可以做到这一点。单元测试可能会更难,但如果您不想使用接口,则不需要

标签: c# oop asp.net-core dependency-injection


【解决方案1】:

为什么将接口注入控制器实际上有效?既然接口只提供了定义,为什么实际的实现似乎也随之而来呢?

接口定义了签名,因此可以通过多种方式实现。

当您将具有具体实现的类传递给控制器​​构造函数接口参数时,它知道如果该类继承该接口,则所有方法都可用。 这就是它知道它的方式。

 我觉得我应该注入具体类 RepositoryWrapper。

没错,当您连接 DI 时,您将在类中与实现挂钩。 Interface 参数将接受任何实现接口方法的类。

为什么?重点是关注点分离。使用接口可以让你模拟实现,这大大简化了单元测试。

它们还具有灵活性,例如,如果美国的税号是 11 位数,而澳大利亚的税号是 8 位数。好吧,您可以为 USA 连接一个具有 11 位功能和 Oz 的 8 位功能的类。如果您没有接口,则只能传入 11 或 8 - 可能会迫使您拥有两个以相同方式运行但行为略有不同的类。使用接口为您提供了实现灵活性。

它是 SOLID 原则的一部分,接口隔离原则:低耦合,高内聚和依赖倒置原则:抽象不应依赖于细节。

【讨论】:

  • 嗯,任何一点都可以用抽象类来解决。
  • 我喜欢@SirRufo 的评论,这个答案主要关注像 OP 所问的接口,但你说得对,我们不应该忘记我们可以使用抽象类来做到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-03
  • 2015-01-15
  • 1970-01-01
  • 2017-12-19
  • 2017-06-17
  • 1970-01-01
相关资源
最近更新 更多