构建一个动态表达式树要过滤的集合属性 [英] Building a dynamic expression tree to filter on a collection property
问题描述
我想建立一个lambda表达式,将与他人合并成一个相当大的表达式树进行过滤。直到我需要通过一个子集属性过滤这工作得很好。
你如何建立一个Lambda表达式将过滤用任何()在集合的属性,该属性?
CurrentDataSource:是根对象的属性。
例.Offices.Where(O => o.base_Trades.Any(T => t.Name ==测试))
这是我会怎么静态构建表达式,但我需要动态地生成它。抱歉的混乱
编辑:这是我如何处理不太复杂的表达式一个片段:
的IQueryable<办公室及GT; officeQuery = CurrentDataSource.Offices.AsQueryable<办公室及GT;();
ParameterExpression PE = Expression.Parameter(typeof运算(厅),办公室);
ParameterExpression TPE = Expression.Parameter(typeof运算(工种),交易);
表达SimpleWhere = NULL;
表达ComplexWhere = NULL;
的foreach(ServerSideFilterObject FO在ssfo)
{
SimpleWhere = NULL;
的foreach(在fo.FilterValues字符串值)
{
如果(!CollectionProperties.Contains(fo.PropertyName))
{
//这里处理单拉姆达逻辑。
表达左= Expression.Property(PE的typeof(办公室).GetProperty(fo.PropertyName));
表达权= Expression.Constant(值);
如果(SimpleWhere == NULL)
{
SimpleWhere = Expression.Equal(左,右);
}
,否则
{
表达E1 = Expression.Equal(左,右);
SimpleWhere = Expression.Or(SimpleWhere,E1);
}
}
,否则
{
//此处把手内收集的lambda逻辑。
表达左= Expression.Property(TPE的typeof(交易).GetProperty(姓名));
表达权= Expression.Constant(值);
表达InnerLambda = Expression.Equal(左,右);
//问题区域。
表达OfficeAndProperty = Expression.Property(PE的typeof(办公室).GetProperty(fo.PropertyName));
表达OuterLambda = Expression.Call(OfficeAndProperty的typeof(交易).GetMethod(任意,新类型[] {typeof运算(表情)}),InnerLambda);
如果(SimpleWhere == NULL)
SimpleWhere = OuterLambda;
,否则
SimpleWhere = Expression.Or(SimpleWhere,OuterLambda);
}
}
如果(ComplexWhere == NULL)
ComplexWhere = SimpleWhere;
,否则
ComplexWhere = Expression.And(ComplexWhere,SimpleWhere);
}
MethodCallExpression whereCallExpression = Expression.Call(typeof运算(可查询),去哪儿,新类型[] {} officeQuery.ElementType,officeQuery.Expression,Expression.Lambda<&Func键LT;办公,布尔>> (ComplexWhere,新ParameterExpression [] {} PE));
=结果与officeQuery.Provider.CreateQuery LT;办公室及GT;(whereCallExpression);
找到了解决办法。我不是在寻找之前正确的地方的任何方法。
表达左= Expression.Property(TPE的typeof(交易).GetProperty(姓名));
表达权= Expression.Constant(值);
表达InnerLambda = Expression.Equal(左,右);
表达式来; Func键<贸易,布尔>> innerFunction = Expression.Lambda<&Func键LT;贸易,布尔>>(InnerLambda,TPE);
法= typeof运算(可枚举).GetMethods()式。(M => m.Name ==任何与&&安培; m.GetParameters()长度== 2)。单().MakeGenericMethod(typeof运算(工种));
OuterLambda = Expression.Call(方法,Expression.Property(PE的typeof(办公室).GetProperty(fo.PropertyName)),innerFunction);
I am trying to build a lambda expression that will be combined with others into a rather large expression tree for filtering. This works fine until I need to filter by a sub collection property.
How do you build a Lambda expression that will filter using Any() on a property of a collection which is a property of the root object?
Example:
CurrentDataSource.Offices.Where(o => o.base_Trades.Any(t => t.Name == "test"))
This is how I would build the expression statically but I need to build it dynamically. Sorry for the confusion.
Edit: Here is a snippet of how I handle the less complicated expressions:
IQueryable<Office> officeQuery = CurrentDataSource.Offices.AsQueryable<Office>();
ParameterExpression pe = Expression.Parameter(typeof(Office), "Office");
ParameterExpression tpe = Expression.Parameter(typeof(Trades), "Trades");
Expression SimpleWhere = null;
Expression ComplexWhere = null;
foreach (ServerSideFilterObject fo in ssfo)
{
SimpleWhere = null;
foreach (String value in fo.FilterValues)
{
if (!CollectionProperties.Contains(fo.PropertyName))
{
//Handle singleton lambda logic here.
Expression left = Expression.Property(pe, typeof(Office).GetProperty(fo.PropertyName));
Expression right = Expression.Constant(value);
if (SimpleWhere == null)
{
SimpleWhere = Expression.Equal(left, right);
}
else
{
Expression e1 = Expression.Equal(left, right);
SimpleWhere = Expression.Or(SimpleWhere, e1);
}
}
else
{
//handle inner Collection lambda logic here.
Expression left = Expression.Property(tpe, typeof(Trades).GetProperty("Name"));
Expression right = Expression.Constant(value);
Expression InnerLambda = Expression.Equal(left, right);
//Problem area.
Expression OfficeAndProperty = Expression.Property(pe, typeof(Office).GetProperty(fo.PropertyName));
Expression OuterLambda = Expression.Call(OfficeAndProperty, typeof(Trades).GetMethod("Any", new Type[] { typeof(Expression) } ),InnerLambda);
if (SimpleWhere == null)
SimpleWhere = OuterLambda;
else
SimpleWhere = Expression.Or(SimpleWhere, OuterLambda);
}
}
if (ComplexWhere == null)
ComplexWhere = SimpleWhere;
else
ComplexWhere = Expression.And(ComplexWhere, SimpleWhere);
}
MethodCallExpression whereCallExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { officeQuery.ElementType }, officeQuery.Expression, Expression.Lambda<Func<Office, bool>>(ComplexWhere, new ParameterExpression[] { pe }));
results = officeQuery.Provider.CreateQuery<Office>(whereCallExpression);
Found the solution. I wasn't looking for the any method in the right place before.
Expression left = Expression.Property(tpe, typeof(Trades).GetProperty("Name"));
Expression right = Expression.Constant(value);
Expression InnerLambda = Expression.Equal(left, right);
Expression<Func<Trades, bool>> innerFunction = Expression.Lambda<Func<Trades, bool>>(InnerLambda, tpe);
method = typeof(Enumerable).GetMethods().Where(m => m.Name == "Any" && m.GetParameters().Length == 2).Single().MakeGenericMethod(typeof(Trades));
OuterLambda = Expression.Call(method, Expression.Property(pe, typeof(Office).GetProperty(fo.PropertyName)),innerFunction);
这篇关于构建一个动态表达式树要过滤的集合属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!