Общие интерфейсы, тип которых реализует другой интерфейс
Может кто-нибудь объяснить, почему это не работает.
У меня есть два контекста БД. И один общий метод с разными типами возврата и разными запросами.
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
тип.