web-dev-qa-db-ja.com

IQueryable <T>を実装するList <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

25
Sly

問題の理由は、AsQueryableを実行すると、オブジェクトがすでにIQueryableを実装しているかどうかがチェックされ、はいの場合はそれが返されるためです。

このチェックを実行しないAsQueryableの代わりにnew EnumerableQuery<T>(this)を使用します。


.net 3.5の回避策:

return ((IEnumerable<T>)this).Select(x=>x).AsQueryable()

最初にIEnumerable<T>にキャストするため、選択されたSelectメソッドはEnumerable.SelectではなくQueryable.Selectになります。 ID選択は、IQueryable<T>を実装しない新しいオブジェクトを返すため、AsQueryableに実装されているかどうかのチェックは失敗します。

29
CodesInChaos

base.AsQueryable()の代わりにthis.AsQueryable()を使用してみてください。

1
Daniel A. White