Список <T> для реализации IQueryable <T>
Я пытаюсь создать макет для моего интерфейса IRepository
:
public interface IRepository<T> : ICollection<T>, IQueryable<T>
{
}
С помощью этой реализации:
public class RepositoryFake<T> : List<T>, IRepository<T>
{
public Expression Expression
{
get
{
return this.AsQueryable().Expression;
}
}
public Type ElementType
{
get
{
return this.AsQueryable().ElementType;
}
}
public IQueryProvider Provider
{
get
{
return this.AsQueryable().Provider;
}
}
}
Но когда я его использую, я получаю исключение StackOverflow
. Как правильно реализовать этот интерфейс, чтобы иметь возможность использовать только List
в качестве репозитория?
Использование очень просто
[Test]
public void Test()
{
RepositoryFake<User> users = new RepositoryFake<User>();
users.Add(new User());
List<User> list = (from user in users
where user.Id == "5"
select user).ToList();
Assert.That(list, Is.Empty);
}
Вот скриншот исключения:
![Exception]()
Ответы
Ответ 1
Причиной вашей проблемы является то, что если вы выполняете AsQueryable
, он проверяет, реализует ли объект IQueryable
, и если да возвращает его.
Используйте new EnumerableQuery<T>(this)
вместо AsQueryable
, который не выполняет эту проверку.
Обходной путь для .net 3.5:
return ((IEnumerable<T>)this).Select(x=>x).AsQueryable()
Сначала добавляется IEnumerable<T>
, поэтому выбранный Select
метод будет Enumerable.Select
not Queryable.Select
. Затем идентификатор выбирает новый объект, который не реализует IQueryable<T>
, поэтому проверка, выполнена ли в AsQueryable
, не выполняется.
Ответ 2
Попробуйте использовать base.AsQueryable()
вместо this.AsQueryable()
.