使用表达式的LINQ过滤器实现 [英] LINQ Filter Implementation with Expressions

查看:122
本文介绍了使用表达式的LINQ过滤器实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在MVC4,我提供的搜索框,用户搜索表中的任意值。
所以我在C#



需要帮助多个表达式相结合,形成单一的表达 <落实在服务器端一般过滤器条件/ p>

 表达式来; Func键< T,BOOL>> 



例如:



表列



MenuText,角色名称(Role.Name映射),ActionName



现在如果用户在ABC的搜索框,可以在任何行中显示的列,需要过滤输入。



模式

 公共类菜单
{
公共字符串MenuText {获取;集;}
公共角色角色{获取;集;}
公共字符串ActionName {获取;集;}
}

公共类角色
{
公字符串名称{;设置;}
}

到目前为止,我已经实现

  ///<总结> 
///字符串[]属性property.Name(MenuText,ActionName),包括更深层次的映射名称,如(Role.Name)
///< /总结>
公共静态表达式来; Func键< T,BOOL>> FilterKey< T>(串filterText,PARAMS字符串[]属性)
{
ParameterExpression参数= Expression.Parameter(typeof运算(T));
表达[] = propertyExpressions properties.Select(
X => string.IsNullOrEmpty(x)的GetDeepPropertyExpression(参数x):!NULL).ToArray();

表达式来; Func键< T,BOOL>>谓词= PredicateBuilder.False< T>();
的foreach(在propertyExpressions表达表达式)
{
VAR TOLOWER = Expression.Call(表达式的typeof(串).GetMethod(ToLower将System.Type.EmptyTypes));
VAR像= Expression.Call(TOLOWER的typeof(串).GetMethod(包含),Expression.Constant(filterText.ToLower()));
// TODO:结合表达式,形成单一的表达式来; Func键< T,BOOL>>表达式

}
返回谓语;
}

///<总结>
///要变得更深属性,如Role.Name表达式
///< /总结>
私有静态表达GetDeepPropertyExpression(表达initialInstance,字符串属性)
{
表达式结果= NULL;
的foreach(在property.Split(字符串propertyName的'。'))
{
表达实例=结果? initialInstance;
结果= Expression.Property(例如,propertyName的);
}
返回结果;
}


解决方案

感谢NinjaNye,我已经借BuildOrExpression从而解决了我的问题。



下面是解决方案

 公开静态表达式来; Func键< T,BOOL>> FilterKey< T>(串filterText,PARAMS字符串[]属性)
{
ParameterExpression参数= Expression.Parameter(typeof运算(T));
表达[] = propertyExpressions properties.Select(
X => string.IsNullOrEmpty(x)的GetDeepPropertyExpression(参数x):!NULL).ToArray();

语句,比如= propertyExpressions.Select(表达式=> Expression.Call(表达式的typeof(串).GetMethod(ToLower将Type.EmptyTypes)))选择(TOLOWER =方式>表达.CALL(TOLOWER的typeof(串).GetMethod(包含),Expression.Constant(filterText.ToLower())))骨料和LT; MethodCallExpression,表达>(NULL,(目前,EX)=> BuildOrExpression(电流,前));
返回Expression.Lambda<&Func键LT; T,BOOL>>(如,参数);
}

私有静态表达BuildOrExpression(表达式existingExpression,表达expressionToAdd)
{
如果(existingExpression == NULL)
{
返回expressionToAdd;
}

//建设OR表示每个属性
返回Expression.OrElse(existingExpression,expressionToAdd);
}


私有静态表达GetDeepPropertyExpression(表达initialInstance,字符串属性)
{
表达式结果= NULL;
的foreach(在property.Split(字符串propertyName的'。'))
{
表达实例=结果? initialInstance;
结果= Expression.Property(例如,propertyName的);
}
返回结果;
}


In MVC4 , I am providing Search box to the user to search any value in Table. So I am implementing Generic Filter Condition at server side in C#

Need a help to combine multiple expressions to form single expression

 Expression<Func<T, bool>> 

For Example

Table Columns

MenuText, Role Name (Role.Name mapping), ActionName

Now If user entered in search box for ABC , which can be in any of the rows in shown columns, need to filter.

Model

public class Menu
{
  public string MenuText {get;set;}
  public Role Role {get;set;}
  public string ActionName {get;set;}
}

public class Role
{
  public string Name {get;set;}
}

So far I have implemented

  /// <summary>
    /// string[] properties property.Name (MenuText, ActionName), including deeper Mapping names such as (Role.Name)
    /// </summary>
    public static Expression<Func<T, bool>> FilterKey<T>(string filterText, params string[] properties)
    {
        ParameterExpression parameter = Expression.Parameter(typeof (T));
        Expression[] propertyExpressions = properties.Select(
            x => !string.IsNullOrEmpty(x) ? GetDeepPropertyExpression(parameter, x) : null).ToArray();

        Expression<Func<T, bool>> predicate = PredicateBuilder.False<T>();
        foreach (Expression expression in propertyExpressions)
        {
             var toLower = Expression.Call(expression, typeof(string).GetMethod("ToLower", System.Type.EmptyTypes));
            var like = Expression.Call(toLower, typeof(string).GetMethod("Contains"), Expression.Constant(filterText.ToLower()));
            //TODO: Combine expressions to form single  Expression<Func<T, bool>> expression

        }
        return predicate;
    }

       /// <summary>
        ///  To Get Deeper Properties such as Role.Name Expressions
        /// </summary>
       private static Expression GetDeepPropertyExpression(Expression initialInstance, string property)
        {
            Expression result = null;
            foreach (string propertyName in property.Split('.'))
            {
                Expression instance = result ?? initialInstance;
                result = Expression.Property(instance, propertyName);
            }
            return result;
        }

解决方案

Thanks to NinjaNye , I have borrowed BuildOrExpression which resolved my problem

Here is the solution

   public static Expression<Func<T, bool>> FilterKey<T>(string filterText, params string[] properties)
        {
            ParameterExpression parameter = Expression.Parameter(typeof (T));
            Expression[] propertyExpressions = properties.Select(
                x => !string.IsNullOrEmpty(x) ? GetDeepPropertyExpression(parameter, x) : null).ToArray();

            Expression like= propertyExpressions.Select(expression => Expression.Call(expression, typeof (string).GetMethod("ToLower", Type.EmptyTypes))).Select(toLower => Expression.Call(toLower, typeof (string).GetMethod("Contains"), Expression.Constant(filterText.ToLower()))).Aggregate<MethodCallExpression, Expression>(null, (current, ex) => BuildOrExpression(current, ex));
            return  Expression.Lambda<Func<T, bool>>(like, parameter);
        }

        private static Expression BuildOrExpression(Expression existingExpression, Expression expressionToAdd)
        {
            if (existingExpression == null)
            {
                return expressionToAdd;
            }

            //Build 'OR' expression for each property
            return Expression.OrElse(existingExpression, expressionToAdd);
        }


       private static Expression GetDeepPropertyExpression(Expression initialInstance, string property)
        {
            Expression result = null;
            foreach (string propertyName in property.Split('.'))
            {
                Expression instance = result ?? initialInstance;
                result = Expression.Property(instance, propertyName);
            }
            return result;
        }

这篇关于使用表达式的LINQ过滤器实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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