如何在表达式树中写入string.Contains(someText) [英] How to write string.Contains(someText) in expression Tree

查看:123
本文介绍了如何在表达式树中写入string.Contains(someText)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是本教程我正在学习表达式树.

This is the tutorial I'm following to learn Expression Tree.

我要显示超过35列,但用户可以选择一次显示10列.因此,一个用户在搜索框中键入内容,我只想搜索用户可见的列.

I've more than 35 columns to display, but the user can chose to display 10 columns at once. So one the user type something in the search box, I want to search only the columns that are visible to the user.

SELECT FirstName, LastName, Address, ..., State
FROM Students
WHERE Id == @Id col1 AND (
      FirstName LIKE '%@searchText%' OR 
      LastName LIKE '%@searchText%' OR 
      Address LIKE '%@searchText%' OR 
      ...
      State LIKE '%@searchText%')

回到Linq,这就是我要完成的方式:

Back to Linq, this is how I'm trying to accomplish it:

var result = db.Students
    .Where(GetPredicate(id, listOfColumns))
    .ToList();

这是私有方法:

private Expression<Func<Student, bool>> GetPredicate(int id, List<string> listOfColumns)
{
   ParameterExpression pe = Expression.Parameter(typeof(Student), "s");

   Expression left0 = Expression.Property(pe, "Id");
   Expression right0 = Expression.Constant(id);
   Expression e0 = Expression.Equal(left0, right0);

   //Here ... omitted code because it's not working...
   //

   var expr = Expression.Lambda<Func<Student, bool>>(e0, new ParameterExpression[] { pe });
        return expr;
}

如上所述,它工作正常.但是,我什至写这种方法的原因是只能根据用户选择的列进行过滤.

As it is above, it's working just fine. However, the reason I even wrote this method was to be able to filter only by the user-selected columns.

我希望能够根据用户界面中可见的列进行撰写.

I want to be able to compose based on the column that are visible in the UI.

if(!string.IsNullOrEmpty(searchText))
{
   foreach (string columnName in columnList)
   {
       Expression col = Expression.Property(pe, columnName);
       Expression left = Expression.Call(pe, typeof(string).GetMethod("Contains"));
       Expression right = Expression.Constant(searchText);
       Expression e = Expression.IsTrue(left, right);
   }
}

我完全迷路了.我知道我需要访问字符串类的Contains方法,然后不知道接下来要做什么.想法是得到这样的东西:

I'm completely lost. I know that I need to access the Contains method of the string class then I don't know what next. The Idea is to get something like this:

Where(d => d.Id == id && (d.FirstName.Contains(searchText) 
        || d.LastName.Contains(searchText) 
        || ...
        || d.State.Contains(searchText)))

感谢您的帮助

推荐答案

您非常亲密,只是构造Contains的调用没有右侧:

You are pretty close, except constructing the call of Contains does not have a right side:

Expression col = Expression.Property(pe, columnName);
Expression contains = Expression.Call(
    pe
,   typeof(string).GetMethod("Contains") // Make a static field out of this
,   Expression.Constant(searchText)      // Prepare a shared object before the loop
);

一旦有了调用表达式,就将它们与OrElse结合起来以生成lambda的主体.您可以使用循环来实现,也可以使用LINQ:

Once you have your call expressions, combine them with OrElse to produce the body of your lambda. You can do it with loops, or you can use LINQ:

private static readonly MethodInfo Contains = typeof(string).GetMethod(nameof(string.Contains));

public static Expression<Func<Student,bool>> SearchPredicate(IEnumerable<string> properties, string searchText) {
    var param = Expression.Parameter(typeof(Student));
    var search = Expression.Constant(searchText);
    var components = properties
        .Select(propName => Expression.Call(Expression.Property(param, propName), Contains, search))
        .Cast<Expression>()
        .ToList();
    // This is the part that you were missing
    var body = components
        .Skip(1)
        .Aggregate(components[0], Expression.OrElse);
    return Expression.Lambda<Func<Student, bool>>(body, param);
}

这篇关于如何在表达式树中写入string.Contains(someText)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆