Почему кажется, что этот интерфейс обеспечивает реализацию? - PullRequest
1 голос
/ 25 сентября 2019

Я следовал учебному пособию, создал серверную часть с EF Core и внедрил шаблон репозитория.

Сначала я создал интерфейс репозитория и базовый класс репозитория, который предоставляет базовые методы CRUD.Затем я создал отдельные интерфейсы и репозитории для каждой из моих сущностей для любых пользовательских методов, которые мне нужны для взаимодействия с данными этих конкретных классов.

Во-вторых, я создал интерфейс и конкретный класс с именами IRepositoryWrapper и RepositoryWrapper.Чтобы определить репозитории для возврата и метод сохранения, а затем реализацию извлечения репозиториев и метода сохранения изменений.

Наконец, я создал контроллер и внедрил IRepositoryWrapper в конструктор контроллера.

Мой вопрос: почему инжекция интерфейса в контроллер действительно работает?Поскольку Интерфейс только дает определение, почему реальная реализация, кажется, пришла с ним?Мне кажется, что я должен вместо этого вводить конкретный класс RepositoryWrapper.

https://code -maze.com / net-core-web-development-part4 / # хранилище

Это работает правильно, я просто задаю вопрос ООП.

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

    }

1 Ответ

2 голосов
/ 25 сентября 2019

Почему инжекция интерфейса в контроллер действительно работает?Поскольку Интерфейс только дает определение, почему реальная реализация, кажется, пришла с ним?

Интерфейс определяет сигнатуры, поэтому его можно реализовать любым количеством способов.

Когда вы передаете класс с конкретной реализацией в аргумент интерфейса конструктора контроллера, он знает, что все методы доступны, если класс наследует интерфейс. Вот как он узнает, что с ним происходит.

Мне кажется, что вместо этого я должен вводить конкретный класс RepositoryWrapper.

Это верно,когда вы подключаете DI, вы подключаете класс к реализации.Аргумент Interface будет принимать любой класс, реализующий методы интерфейса.

Почему?Главное - это разделение проблем.Использование интерфейсов позволяет имитировать реализации, что значительно упрощает модульное тестирование.

Они также допускают гибкость, скажем, если в США налоговые номера составляют 11 цифр, а в Австралии - 8 цифр.Ну, вы можете подключить класс с 11-значным функционалом для США и 8 цифрами для Оз.Если у вас не было Интерфейса, вы могли бы передать только 11 или 8 - вероятно, вы заставили бы вас иметь два класса, которые работают одинаково с немного отличающимся поведением.Использование интерфейсов обеспечивает гибкость реализации.

Это часть принципов SOLID, принципа разделения интерфейсов: низкая связь, высокая когезия и принцип инверсии зависимостей: абстракции не должны зависеть от деталей.

...