Общие интерфейсы, тип которых реализует другой интерфейс

Может кто-нибудь объяснить, почему это не работает.

У меня есть два контекста БД. И один общий метод с разными типами возврата и разными запросами.

      public interface IDataFetcher<T> where T : IMarker
{
    public List<T> GetData();
}
public interface IFetchServiceOne<T> : IDataFetcher<T> where T : IMarker
{
//maybe some methods here
}
public interface IFetchServiceTwo<T> : IDataFetcher<T> where T : IMarker
{
//maybe some different methods here
}

Выполнение:

      public class FetchServiceOne<T> : IFetchServiceOne<T> where T : IMarker
{
    private readonly DBContext _dbContext;

    public FetchServiceOne(DBContext dbContext) => _dbContext = dbContext;

    public List<CrucialData> GetData()
    {
        var example = _dbContext.Test.ToList();
        return example;
    }
}
public class FetchServiceTwo<T> : IFetchServiceOne<T> where T : IMarker
{
    private readonly DBContext _dbContext;

    public FetchServiceTwo(DBContext dbContext) => _dbContext = dbContext;

    public List<CrucialDataTwo> GetData()
    {
        var example = _dbContext.Test2.ToList();
        return example;
    }
}
public class CrucialData: IMarker
{
//some properries
}
public class CrucialDataTwo: IMarker
{
//another properries
}

На выходе получаю ошибку компиляции:

Ошибка (активная) CS0738 «FetchService» не реализует член интерфейса «IDataFetcher.GetData()». 'FetchService.GetData()' не может реализовать 'IDataFetcher.GetData()', потому что он не имеет соответствующего возвращаемого типа 'List'.

1 ответ

Это выглядит какIFetchServiceOneиIFetchServiceTwo(и их реализации) должны быть «конкретными» интерфейсами, реализующими закрытые версииIDataFetcher. То есть:

      public interface IFetchServiceOne : IDataFetcher<CrucialData>
{
    //maybe some methods here
}

public class FetchServiceOne : IFetchServiceOne
{
    // ...

    public List<CrucialData> GetData()
    {
        // implementation ...
        return default;
    }
}

В противном случае вы не можете гарантировать, что запрос пользователя будетCrucialDataдляFetchServiceOne(т.е.FetchServiceOne<CrucialDataTwo>.GetData()...)

Или просто:

      public class FetchServiceOne : IDataFetcher<CrucialData>
{
   // ...
}

Без необходимости введения промежуточного интерфейса.

Обратите внимание, что для EF вы можете создать общую реализацию черезSetметод при необходимости:

      public class FetchServiceOne<T> : IDataFetcher<T> where T : IMarker
{
    private readonly DBContext _dbContext;

    public FetchServiceOne(DBContext dbContext) => _dbContext = dbContext;

    public List<T> GetData()
    {
        var example = _dbContext.Set<T>.ToList();
        return example;
    }
}

Но это не удастся во время выполнения, если нет соответствияDbSetнастройка свойств для предоставленныхTтип.

Другие вопросы по тегам