看起来你的存储库实现在某种意义上存在一个重大缺陷,即调用者不知道他只能传递某些类型的参数(例如,看起来我可以执行FindAll<int>(v => v > 0)
,但实际上,底层实现仅适用于MyEntity
)。换句话说,它试图变得过于“聪明”,不直观且容易出错。
解决这个问题的一种方法是引入接口/基类:
public interface IRepository<T>
{
IEnumerable<T> FindAll<T>(Expression<Func<T, bool>> predicate);
}
public abstract class Repository<T> : IRepository<T>
{
private readonly IEnumerable<T> _entities;
protected Repository(IEnumerable<T> entities)
{
_entities = entities;
}
public IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate)
{
return _entities.Where(predicate);
}
}
public class MyEntityRepository : Repository<MyEntity>
{
public MyEntityRepository() : base(new MyDbContext().MyEntities) { }
}
在上面的例子中,我只是为了演示目的而提到了
MyDbContext
(如果您使用过
Entity Framework,那么它看起来会更加熟悉)。
现在,您可以实例化
MyEntityRepository
并在整个应用程序中使用它。如果您正在使用某种IoC,您可以稍微修改代码:
public interface IMyEntityRepository : IRepository<MyEntity>
{
}
public class MyEntityRepository : Repository<MyEntity>, IMyEntityRepository
{
}
现在,您可以轻松地在应用程序中注入和模拟
IMyEntityRepository
。
希望这能帮到您。
更新
事实证明,由于给定的实现仅用于测试目的,因此您可以尝试以下方式来生成所需类型的表达式:
return MyEntities.Where(Expression.Lambda<Func<MyEntity, bool>>(predicate.Body,
predicate.Parameters)).Cast<T>()
如果需要明确的参数,您还可以对lambda参数进行一些转换。