Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to convert Expression<Func<T, bool>> to Expression<Func<MyType, bool>>?

I have a repository class with some generic methods. One is

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 which uses in-memory objects instead of a database. The TestRepository overrides the FindAll method and I want to control what is returned. 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 a Expression<Func<MyEntity, bool>>.

How can I cast/convert the generic expression to the strongly typed expression?

like image 737
Nicklas Møller Jepsen Avatar asked Nov 15 '13 10:11

Nicklas Møller Jepsen


1 Answers

You can do something like this. Not sure whether it's a good idea, but it works. Basically, your overload can compare the type parameter T to your entity class. If the predicate has the right type, you can cast. Otherwise, you don't have anything 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];
}

Usage:

var res = FindAll((MyEntity y) => y.x % 2 == 0).ToList();
Console.WriteLine(res.Count);
like image 108
Rob Avatar answered Oct 21 '22 03:10

Rob