Почему в этом случае требуется ковариация интерфейса? - PullRequest
0 голосов
/ 01 октября 2018

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

Структура

  1. Базовый фильтр - содержит логику и принимает служебный параметр в конструкторе:

    public abstract class BaseFilter
    {
        ...
        public BaseFilter(IService<IEntity> service)
        ...
    }
    
  2. Общий сервисный интерфейс : public interface IService<TEntity>
  3. Базовый объект : public class BaseEntity : IEntity
  4. Конкретный объект : public class ConcreteEntity : BaseEntity
  5. Бетонный фильтр :

    public class ConcreteFilter : BaseFilter
    {
        public ConcreteFilter(IService<ConcreteEntity> service) : base(service)
        {
        }
    }
    

Это базовая структура решения - общий уровень услуг и инфраструктуры, которыйзатем часто получают с помощью платформо-зависимых (ConcreteFilter в примере) классов, чтобы передать платформо-зависимые сущности в качестве общих параметров.

Проблема

Выше не компилируется:

Argument 1: cannot convert from 'Service<ConcreteEntity>' to 'Service<IEntity>'

Я знаю, что могу исправить это с помощью ковариантного сервисного интерфейса:

public class IService<out TEntity>

Однако я бы хотел этого избежать.В этой платформе (назовем это ConcretePlatform ) универсальный параметр всегда будет ConcreteEntity, поскольку он так и подключен в контейнере.Я не хочу ограничивать универсальный параметр в external-position , потому что у меня есть перегрузки, которые принимают TEntity.C # уже проверяет во время компиляции, реализует ли данный тип IEntity, что, насколько я могу судить, является типобезопасным.Я не могу предвидеть проблему, но даже она может случиться - у меня все в порядке с исключение времени выполнения , так как это подключение зависимостей, и оно не может проскочить в производстве, если только в случаеосновной надзор за разработчиками.

Возможное исправление - использовать вместо этого IEntity в качестве типа параметра, а затем приводить к TEntity внутри каждого метода, однако это приведение полностью избыточно.

Мысли

  1. Являются ли какие-либо мои претензии / понимания неверными?Если да, пожалуйста, объясните, как и почему.
  2. Я бы хотел избежать дисперсии ко / контра, потому что это должно быть уместно, если я попытаюсь как-то смешать базовый и производный типы, что вовсе не то, что я делаю.Кроме того, это неизбежно приведет к заливке образцов.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...