vendredi 29 décembre 2017

lambda expression cast from interface

I have following interface:

public interface IHasSchoolId
{
    long? SchoolId { get; set; }
}

and following entity:

public class Student : IHasSchoolId
{
    long? SchoolId { get; set; }
}

then there is following entity manager implementing empty interface IEntityManager<T>:

public class HasSchoolIdManager: IEntityManager<IHasSchoolId>
{
    public static Expression<Func<IHasSchoolId, bool>> Filter()
    {
        return x=> x.SchoolId != null; //this is just an example
    }
}

and finally I have following method:

private Expression<Func<TEntity, bool>> GetFilters<TEntity>()
{
    Expression<Func<TEntity, bool>> result = null;
    var entityManagers = //geting entitymanagers that are assinable to TEntity, like the one above and a lot more like IEntityManager<Student> itself
    foreach (var entityManager in entityManagers)
    {
        var filterMethod = entityManager.GetMethod("Filter");
        if (filterMethod != null)
            result = AndAlso(result, (Expression<Func<TEntity, bool>>) filterMethod.Invoke(null, null)); //this line throws exception
    }
    return result;
}

and then when I'm calling the method like GetFilters<Student>() im getting following exception:

System.InvalidCastException: 'Unable to cast object of type 'System.Linq.Expressions.Expression[System.Func[WebCore.Models.Infrastructure.Interfaces.IHasSchoolId,System.Boolean]]' to type 'System.Linq.Expressions.Expression[System.Func[WebCore.Models.Student,System.Boolean]]'.'

by the way, this is my AndAlso method which works fine:

private Expression<Func<T, bool>> AndAlso<T>(
        Expression<Func<T, bool>> expr1,
        Expression<Func<T, bool>> expr2)
{
    if (expr1 == null)
        return expr2;
    if (expr2 == null)
        return expr1;
    ParameterExpression param = expr1.Parameters[0];
    if (ReferenceEquals(param, expr2.Parameters[0]))
    {
        return Expression.Lambda<Func<T, bool>>(
            Expression.AndAlso(expr1.Body, expr2.Body), param);
    }
    return Expression.Lambda<Func<T, bool>>(
        Expression.AndAlso(
            expr1.Body,
            Expression.Invoke(expr2, param)), param);
}

and here is my empty IEntityManager interface:

public interface IEntityManager<T>
{

}

Note: not all my entities implements IHasSchoolId interface, there are many other interfaces, this is just an example

i think my question is, how to cast from Expression<Func</*an interface*/, bool>> to Expression<Func</*a class that implements that interface*/, bool>> using reflection because as you can see, im calling the filter method using reflection





Aucun commentaire:

Enregistrer un commentaire