我想创建动态拉姆达表达式,以便我可以使用一组过滤参数来过滤列表。这是我到目前为止有:动态递归拉姆达表达式
的表达式使用内置的方法波纹管,其中T是列表的对象类型
public static Expression<Func<T, bool>> GetExpression<T>(IList<DynamicFilter> filters)
{
if (filters.Count == 0)
return null;
ParameterExpression param = Expression.Parameter(typeof(T), "t");
Expression exp = null;
if (filters.Count == 1)
exp = GetExpression<T>(param, filters[0]);
[...]
return Expression.Lambda<Func<T, bool>>(exp, param);
}
private static Expression GetExpression<T>(ParameterExpression param, DynamicFilter filter)
{
MemberExpression member = Expression.Property(param, filter.PropertyName);
ConstantExpression constant = Expression.Constant(filter.Value);
[...]
return Expression.Call(member, filterMethod, constant);
}
我再打电话
List<Example> list = ...;
var deleg = ExpressionBuilder.GetExpression<Example>(dynFiltersList).Compile();
list = list.Where(deleg).ToList();
这个工程只是正如所期望的那样,只包含简单类型的对象,但如果内部存在复杂类型,代码将不再工作。例如,假设我在Example类中有一个自定义类型Field的成员,并且Field有一个字符串属性Value。如果filter.PropertyName
是'Field0'(字段类型),代码将工作得很好,但如果我有'Field0.Value',我会得到一个明显的错误,指出在类Example中没有名为'Field0.Value'的属性。
我试图修改表达构建方法,像这样:
MemberExpression member = null;
if (filter.PropertyName.Contains('.'))
{
string[] props = filter.PropertyName.Split('.');
ParameterExpression param1 = Expression.Parameter(typeof(T).GetProperty(props[0]).PropertyType, "t1");
member = Expression.Property(param1, props[0]);
}
else
{
member = Expression.Property(param, filter.PropertyName);
}
但后来我在编译时表达了一个Lambda parameter not in scope
错误。我有点理解为什么我得到这个错误,但我不知道如何使这项工作。
底线是我需要使表达式构建方法在形成MemberExpression时递归地工作。我最终需要获得一个list = list.Where(deleg).ToList();
,这意味着像这样的list = list.Where(obj => obj.Field0.Value == 'something').ToList();
我刚开始使用表达式,所以我真的不知道在这方面太多,但任何帮助将不胜感激。
感谢
它看起来可以工作,但我现在无法测试它。无论如何,我使用Microsoft提供的动态linq库解决了我的问题,如下所示:[在Linq-to-Entities中编写动态Linq查询](http://naspinski.net/post/Writing-Dynamic-Linq-Queries-in- Linq-to-Entities.aspx)与自定义表达式构建器相结合。 – 2011-10-25 06:11:25
一个很好的解决方案!第一次实施并运行。 – paqogomez 2014-02-10 20:37:30