从某种意义上说,您的存储库实现似乎存在重大缺陷,即调用者不知道他只能传递某些类型的参数(例如,看起来我可以这样做FindAll<int>(v => v > 0)
,但实际上,底层实现仅适用于MyEntity
)。换句话说,它试图变得过于“聪明”,它不直观且容易出错。
解决此问题的一种方法是引入接口/基类:
public interface IRepository<T>
{
IEnumerable<T> FindAll<T>(Expression<Func<T, bool>> predicate);
}
// A base class that can carry helper functionality.
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);
}
}
// Concrete implementation
public class MyEntityRepository : Repository<MyEntity>
{
public MyEntityRepository() : base(new MyDbContext().MyEntities) { }
}
在上面的示例中,我仅出于演示目的而引用(因此,如果您使用Entity FrameworkMyDbContext
,它看起来会更熟悉一些)。
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 参数应用一些转换。