构建动态表达式树以过滤集合属性
我正在尝试构建一个lambda表达式,它将与其他表达式组合成一个相当大的表达式树进行过滤。 这工作正常,直到我需要通过子集合属性进行过滤。
如何构建一个Lambda表达式,它将在集合的属性上使用Any()进行过滤,该集合属性是根对象的属性?
例:
CurrentDataSource.Offices.Where(o => o.base_Trades.Any(t => t.Name == "test"))
这是我如何静态构建表达式,但我需要动态构建它。 对困惑感到抱歉。
编辑:这是我如何处理不太复杂的表达式的片段:
IQueryable officeQuery = CurrentDataSource.Offices.AsQueryable(); 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>(ComplexWhere, new ParameterExpression[] { pe })); results = officeQuery.Provider.CreateQuery(whereCallExpression);
找到了解决方案。 我之前没有在正确的地方寻找任何方法。
Expression left = Expression.Property(tpe, typeof(Trades).GetProperty("Name")); Expression right = Expression.Constant(value); Expression InnerLambda = Expression.Equal(left, right); Expression> innerFunction = Expression.Lambda>(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);
请不要这样做,你真正希望它使用一个名为dynamic linq的库。 http://nuget.org/packages/DynamicLINQ
您可以将查询存储为字符串,并且它支持非常复杂的查询。 表达树是一场噩梦。
您列出的示例将根据您的评论工作。 这是我合作的一个例子:
Templates.Where(t => t.TemplateFields.Any(f => f.Required == 'Y'))
我们有具有特定字段集合的模板,可能需要这些字段。 所以我可以获得上面那个语句需要任何字段的模板。
希望这有助于…或至少证实你正在尝试做什么。 如果您对此有更多疑问,请告诉我,我会详细说明。
祝好运!
提供的代码
CurrentDataSource.Offices.Where(o => o.base_Trades.Any(t => t.Name == "test"))
应该工作,只要o.base_Trades
实现IEnumerable
。 如果o.base_Trades
只实现IEnumerable
,你需要使用Cast
如果你可以确定o.base_Trades
中的所有元素都是你的Trade
类型或o.base_Trades
OfType
如果可能有元素其他(不兼容)类型。
那将是这样的:
CurrentDataSource.Offices .Where(o => o.base_Trades.Cast.Any(t => t.Name == "test"))
- Wson中的JsonConvert.DeserializeObject和“d”包装器
- 在WCF服务中传递接口?
- 当WCF服务运行批处理文件时,XCopy或MOVE不起作用。 为什么?
- 如何在不使用ping的情况下检查Web服务是否已启动并运行?
- 如何在ASP.NET / WCF中定期执行某些操作?
- 在WCF服务中覆盖ToString方法
- 在.NET Core项目中找不到System.ServiceModel
- 如何通过json Web服务接受参数(包括图像)并将其存储到SQL Server数据库中?
- 在IIS6下,jquery ajax发布到WCF服务的post数据(方法参数)在IE中被删除(除非fiddler正在运行)