如何在Devforce中组合不同类型的c#表达式
本文关键字:同类型 表达式 组合 Devforce | 更新日期: 2023-09-27 18:16:21
我写了一些谓词,想用它们来构造一个实体查询。
通常如果我有一个类型为EntityA
的实体,我会写这样的表达式Expression<Func<EntityA, bool>>
。
我想完成的是在EntityA
类型的查询中使用Expression<Func<EntityB, bool>>
。
假设EntityA
有EntityB
的集合。我对EntityA
有一个谓词,如:
public static Expression<Func<EntityA, bool>> HasId(int id)
{
return p => p.Id == id;
}
现在在查询我的EntityB时,我希望能够使用这个谓词,以避免在Expression<EntityB, bool>> (with p => p.EntityA.Id == id)
中重写它。
我想要这样的东西:
Expression<Func<EntityB, bool>> predicates = p => **initial condition on EntityB**
var myfunc = HasId(12).Compile();
predicates = predicates.And(p => myfunc(p.EntityA));
这个语法不起作用。
如何在Expression<Func<EntityB,bool>>
谓词中使用Expression<Func<EntityA, bool>>
?
* EDIT *
忘了说我在我的项目中使用Devforce(来自Ideablade)。谓词。并且是来自他们(我最初以为我来自系统)。
错误信息是:
Unknown Expression type: Invoke(value(UserQuery+<>c__DisplayClass1)。myfunc, p. entitya)
, Stacktrace是:
à IdeaBlade.Linq.ExpressionVisitor.VisitExpressionCore(Expression e)
à IdeaBlade.Linq.TransformExpressionVisitor.VisitExpressionCore(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpression(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpressionCore(Expression e)
à IdeaBlade.Linq.TransformExpressionVisitor.VisitExpressionCore(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpression(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpressionCore(Expression e)
à IdeaBlade.Linq.TransformExpressionVisitor.VisitExpressionCore(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpression(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpressionCore(Expression e)
à IdeaBlade.Linq.TransformExpressionVisitor.VisitExpressionCore(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpression(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpressionCore(Expression e)
à IdeaBlade.Linq.TransformExpressionVisitor.VisitExpressionCore(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpression(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.<VisitExpressions>b__0(Expression e)
à System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
à System.Linq.Buffer`1..ctor(IEnumerable`1 source)
à System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpressions(IEnumerable`1 expressions)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpressionCore(Expression e)
à IdeaBlade.Linq.TransformExpressionVisitor.VisitExpressionCore(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.VisitExpression(Expression expr)
à IdeaBlade.Linq.ExpressionVisitor.Visit(Expression expr)
à IdeaBlade.EntityModel.EntityQuery`1.ProcessExpression(Expression e)
à IdeaBlade.EntityModel.EntityQuery`1..ctor(Expression expression, IQueryable queryable)
à IdeaBlade.EntityModel.EntityQuery`1.System.Linq.IQueryProvider.CreateQuery[TElement](Expression expression)
à System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate)
à IdeaBlade.EntityModel.EntityQueryExtensions.Where[TSource](IEntityQuery`1 source1, Expression`1 predicate)
您可以动态构建Expression<EntityB,bool>
谓词,但它的可重用性是有问题的。请注意,如果使用实体框架,则不支持调用表达式。
——更新
此操作有效且可重用:
public static Expression<Func<T2, bool>> SubPredicate<T1, T2>( Expression<Func<T1, bool>> predicate, Expression<Func<T2, T1>> selector )
{
var parms = selector.Parameters;
var a = Expression.Invoke( selector, parms );
var invocation = Expression.Invoke( predicate, a );
return ( Expression<Func<T2, bool>> )Expression.Lambda( invocation, parms );
}
用法:
var filteredResults = list.Where(
SubPredicate<EntityA, EntityB>(
a => a.ID % 2 == 1,
b => b.EntityA )
.Compile() );
——演示:
static void Main( string[] args )
{
var list = new List<EntityB>()
{
new EntityB()
{
ID = 11,
EntityA = new EntityA() { ID = 1 }
},
new EntityB()
{
ID = 22,
EntityA = new EntityA() { ID = 2 }
},
new EntityB()
{
ID = 33,
EntityA = new EntityA() { ID = 3 }
},
};
var filteredResults = list.Where(
SubPredicate<EntityA, EntityB>(
a => a.ID % 2 == 1,
b => b.EntityA )
.Compile() );
foreach( var b in filteredResults )
{
Console.WriteLine( "{0}/{1}", b.ID, b.EntityA.ID );
}
Console.ReadLine();
}