It looks like your repository implementation has a major flaw in a sense that the caller is not aware that he can only pass arguments of certain types (e.g. it looks like I can do FindAll<int>(v => v > 0)
but in fact, the underlying implementation only works with MyEntity
). In other words, it's trying to be too "smart", it's not intuitive and error-prone.
One way of fixing this can be by introducing an interface/base class:
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) { }
}
In the above example I'm referring to MyDbContext
just for demonstration purposes (so it looks a bit more familiar if you worked with Entity Framework).
Now you can instantiate MyEntityRepository
and use it throughout the application. In case you're using some sort of IoC, you can modify the code slightly:
public interface IMyEntityRepository : IRepository<MyEntity>
{
// ...
}
public class MyEntityRepository : Repository<MyEntity>, IMyEntityRepository
{
// ...
}
And now you can easily inject and mock IMyEntityRepository
within your application.
Hope this helps.
UPDATE
As it turns out, since the given implementation is used for testing purposes only, you could try producing the expression of a desired type the following way:
return MyEntities.Where(Expression.Lambda<Func<MyEntity, bool>>(predicate.Body,
predicate.Parameters)).Cast<T>();
You can also apply some casting to the lambda parameter, if explicit one is needed.