为string.Contains构建表达式树

时间:2013-01-30 21:59:39

标签: c# .net-4.0 expression-trees

我正在努力构建表达式树,以便我可以动态地对某些数据进行过滤。

我已经想出了这个,但它在var lambda =

失败了
foreach (var rule in request.Where.Rules)
{
    var parameterExpression = Expression.Parameter(typeof(string), rule.Field);
    var left = Expression.Call(parameterExpression, typeof(string).GetMethod("ToLower", Type.EmptyTypes));
    var right = Expression.Constant(rule.Data.ToLower());
    var method = typeof(string).GetMethod("Contains", new [] { typeof(string) });
    var call = Expression.Call(left, method, right);
    var lambda = Expression.Lambda<Func<T, bool>>(call, parameterExpression);
    query = query.Where(lambda);
}

var rule有一个Field(ex“Name”),我想与rule.Data(ex'tom')中的文本进行比较。因此,如果T.Name.Contains("tom");我希望查询包含记录,否则不是。

var query的类型为IQueryable<T>

编辑:最后让它使用了这段代码:

foreach (var rule in request.Where.Rules)
{
    var parameter = Expression.Parameter(typeof(T), "x");
    var property = Expression.Property(parameter, rule.Field);
    var value = Expression.Constant(rule.Data);
    var type = value.Type; 
    var containsmethod = type.GetMethod("Contains", new[] { typeof(string) });
    var call = Expression.Call(property, containsmethod, value);
    var lambda = Expression.Lambda<Func<T, bool>>(call, parameter);
    query = query.Where(lambda);
}

2 个答案:

答案 0 :(得分:2)

你几乎就在那里,但你的参数表达式应该是T类型,而不是String,你也缺少从名称类型T获取属性的表达式。

你应该大致拥有的是这个

val -> Expression.Constant(typeof(string), rule.Field)
parameter -> Expression.Parameter(typeof(T), "p")
property -> Expression.Property(parameter, "PropertyName")
contains -> Expression.Call(property, containsmethod, val)
equals true -> Expression.True or equals, something like that

我自由发挥所有这一切,因此有效可能有所不同。结果表达式应该是这样的

p => p.Name.Contains(val)

答案 1 :(得分:0)

如果您要创建Where查询,则必须创建lambda,然后在查询时调用Where并传递lambda。 试试这个:

Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(call, parameter);
MethodCallExpression expression = Expression.Call(typeof(Queryable), "Where",
                                    new[] { typeof(T) }, query.Expression, lambda);
query = query.Provider.CreateQuery<T>(expression);

而不是

var result = Expression.IsTrue(call);
query = query.Provider.CreateQuery<T>(result);