我有两个表达式:
Expression<Func<T1, T2>>
Expression<Func<T2, bool>>
我希望将它们结合起来,得到一个新的类型为Expression<Func<T1, bool>> 的表达式,以便在实体框架LINQ中使用。
我使用Expression.Invoke()将它们组合在一起,但不起作用。
//Extensinon method
public static Expression<Func<T1, bool>> Compose<T1, T2>(this Expression<Func<T1, T2>> convertExpr, Expression<Func<T2, bool>> predicate)
=> Expression.Lambda<Func<T1, bool>>(Expression.Invoke(predicate, convertExpr.Body), convertExpr.Parameters.First());
...
Expression<Func<One, Two>> convert;
Expression<Func<Two, bool>> predicate;
Expression<Func<One, bool>> filter=convert.Compose(predicate);
// Works fine
List<One> lst;
lst.AsQueryable().Where(filter);
DbSet<One> src;
// In next line throws runtime NotSupportedException: The LINQ expression node type 'Invoke' is not supported in LINQ to Entities
src.Where(filter);
更新
例如:
public class Book
{
public int Id {get; protected set;}
public string Name {get; protected set;}
public virtual Genre {get; protected set;}
}
public class Genre
{
public int Id {get; protected set;}
public string Name {get; protected set;}
}
...
Expression<Func<Book, Genre>> convert = b=>b.Genre;
Expression<Func<Genre, bool>> predicate = g=>g.Name=="fantasy";
// Need: b=>b.Genre=="fantasy"
Expression<Func<Genre, bool>> filter=convert.Compose(predicate);
// Works fine
List<Book> lst;
lst.AsQueryable().Where(filter);
DbSet<Book> books;
// In next line throws runtime NotSupportedException: The LINQ expression node type 'Invoke' is not supported in LINQ to Entities
books.Where(filter);
ExpressionVisitor
,它本质上是 LINQKit 的Invoke
/Expand
的一个有限版本,称为Apply
,它可以原地展开LambdaExpression
,你可以在这里看到。请注意,当null
是参数时,此特定的Apply
对null
传播有特殊考虑(静态处理null.member
->null
,就像它是null?.member
一样)。 - NetMage