2011-07-20 39 views
25

我试图创建一个模拟我IRepository接口:列表<T>实现IQueryable的<T>

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

+2

“但是,当我使用它” - 显示我们的代码?向我们展示堆栈跟踪? – cdhowie

+0

你想做什么?我最好的猜测是你希望有一些魔法。行为是完全预期的。 – leppie

回答

29

原因您的问题是,如果你执行AsQueryable它会检查对象已经实现了IQueryable和如果是,则返回。

使用new EnumerableQuery<T>(this)而不是AsQueryable它不执行此检查。


解决方法.NET 3.5:

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

首先投射到IEnumerable<T>所以所选择的Select方法将是不Enumerable.SelectQueryable.Select。身份选择将返回一个新的对象,不执行IQueryable<T>,所以检查它是否在AsQueryable实施失败。

+0

它保护了构造函数吗?.. – Sly

+0

以'IEnumerable '为构造函数是公共的。检查http://msdn.microsoft.com/en-us/library/cc190806.aspx至少在.net 4上 – CodesInChaos

+0

@CodeInChaos:.NET 4中的新增功能。 – leppie

1

尝试使用base.AsQueryable()而不是this.AsQueryable()

+0

基类没有这样的扩展 – Sly

+0

因为检查'IQueryable '是否已经实现,所以不会有任何帮助使用运行时类型。这不是虚拟的方法。 – CodesInChaos

相关问题