我有以下界面:
public interface IHasSchoolId
{
long? SchoolId { get; set; }
}
和以下实体:
public class Student : IHasSchoolId
{
long? SchoolId { get; set; }
}
然后有以下实体管理器实现空接口IEntityManager<T>
:
public class HasSchoolIdManager: IEntityManager<IHasSchoolId>
{
public static Expression<Func<IHasSchoolId, bool>> Filter()
{
return x=> x.SchoolId != null; //this is just an example
}
}
最后我有以下方法:
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;
}
然后当我调用类似GetFilters<Student>()
的方法时,我会得到以下异常:
System.InvalidCastException :'无法转换类型为'System.Linq.Expressions.Expression [System.Func [WebCore.Models.Infrastructure.Interfaces.IHasSchoolId,System.Boolean]]'的对象输入'System.Linq.Expressions.Expression [System.Func [WebCore.Models.Student,System.Boolean]]'。'
顺便说一句,这是我的AndAlso方法,它运行良好:
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);
}
这是我的空IEntityManager接口:
public interface IEntityManager<T>
{
}
注意:并非我的所有实体都实现了IHasSchoolId接口,还有很多其他接口,这只是一个例子
我认为我的问题是,如何从Expression<Func</*an interface*/, bool>>
投射到Expression<Func</*a class that implements that interface*/, bool>>
使用反射,因为你可以看到,我使用反射调用过滤器方法
答案 0 :(得分:0)
这是我最后做的事情:
Expression<Func<T, bool>> expression = null;
var managers = GetEntityManagers<T>();
foreach (var manager in managers)
{
var expr2 = manager.GetMethod("Filter")?.Invoke(null, null) as dynamic;
if (expr2 == null) continue;
var transformedExpr = Transform<T>(expr2) as Expression<Func<T, bool>>;
expression = expression == null ? transformedExpr : expression.AndAlso(transformedExpr);
}
这是变换函数:
private class Visitor : ExpressionVisitor
{
private Expression _parameter;
public Visitor(Expression parameter)
{
_parameter = parameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
return _parameter;
}
}
private static Expression<Func<T, bool>> Transform<T>(dynamic expression)
{
ParameterExpression parameter = Expression.Parameter(typeof(T));
Expression body = new Visitor(parameter).Visit(expression.Body);
return Expression.Lambda<Func<T, bool>>(body, parameter);
}