Is it possible to convert the expression <Func <T, bool >> to the expression <Func <MyType, bool >>?
I have a repository class with some generic methods. One of them -
public IEnumerable<T> FindAll<T>(Expression<Func<T, bool>> predicate) where T : class { return GetDbSet<T>().Where(predicate); } For unit testing, I have a TestRepository that uses objects in memory instead of a database. TestRepository overrides the FindAll method, and I want to control the return. So I want to be able to do something like this:
public override IEnumerable<T> FindAll<T>(Expression<Func<T, bool>> predicate) { return MyEntities.Where(predicate).Cast<T>(); } But MyEntities.Where() only accepts Expression<Func<MyEntity, bool>> .
How can I convert a generic expression to a strongly typed expression?
You can do something like this. Not sure if this is a good idea, but it works. Basically, your overload can compare a parameter of type T with your entity class. If the predicate is of the correct type, you can use it. Otherwise, you have nothing to return.
public class MyEntity { public int x; } MyEntity[] MyEntitiesList = Enumerable.Range(1,5).Select(y => new MyEntity() { x = y }).ToArray(); public IEnumerable<T> FindAll<T>(Expression<Func<T, bool>> predicate) { if (typeof(T) == typeof(MyEntity)) { return (IEnumerable<T>)MyEntitiesList.Where((predicate as Expression<Func<MyEntity, bool>>).Compile()); } return new T[0]; } Using:
var res = FindAll((MyEntity y) => yx % 2 == 0).ToList(); Console.WriteLine(res.Count); It seems that the implementation of your repository has a major drawback in the sense that the caller does not know that it can only pass arguments of certain types (for example, it looks like I can do FindAll<int>(v => v > 0) , but in fact, only the base implementation works with MyEntity ). In other words, he is trying to be too “smart,” he is not intuitive and error-prone.
One way to fix this could be to introduce 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 mean MyDbContext for demo purposes only (so it looks a little more familiar if you worked with the Entity Framework ).
Now you can create an instance of MyEntityRepository and use it throughout the application. If you use some kind of IoC, you can change the code a bit:
public interface IMyEntityRepository : IRepository<MyEntity> { // ... } public class MyEntityRepository : Repository<MyEntity>, IMyEntityRepository { // ... } And now you can easily type and mock IMyEntityRepository in your application.
Hope this helps.
UPDATE
As it turned out, since this implementation is used only for testing purposes, you can try to produce an expression of the desired type as follows:
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 is required.