【问题标题】:How to pass List of Expression in linq Query如何在 linq Query 中传递表达式列表
【发布时间】:2020-01-25 15:28:15
【问题描述】:

我想使用通用搜索参数为分页创建通用类。我使用反射来获取过滤器属性。它可以使用我不太了解的表达式来实现。任何帮助都将不胜感激。

public IEnumerable<T> ModelPagination(F filters) <-- F class filter properties eg. Name, CNIC for search
        {
            Type C = Type.GetType("filters");
            PropertyInfo[] properties = C.GetProperties();

            foreach (PropertyInfo prop in properties)
            {
                 prop.Name;
            }

            return dbEntity.Where(x => ...... ).ToList(); <--- want to pass each property as lambda for something like x -> x.Name == filters.Name || filters.Name == Null 

        }

【问题讨论】:

    标签: c# linq lambda expression


    【解决方案1】:

    这将构建 lambda 表达式,它将与泛型类型 T 和 Filter 类之间的属性相交并比较它们是否相等,每个单独的属性对也与 AND 条件组合。

    public static IEnumerable<T> ModelPagination<T>(F filter) 
    {
            // all properties which are in the fiter class also present in the generic type T
            var commonPropertyNames = filter
                    .GetType()
                    .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                    .Select(x => x.Name)
                    .Intersect(
                        typeof(T)
                        .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                        .Select(x => x.Name)
                    );
            var argumentExpression = Expression.Parameter(typeof(T), "x");
            var filterConstantExpression = Expression.Constant(filter);
    
            // build the expression
            var expression = (BinaryExpression)null;
            foreach (var propertyName in commonPropertyNames)
            {
                var filterPropertyExpression = Expression.Property(filterConstantExpression, propertyName);
    
                var equalExpression = Expression.Equal(
                    Expression.Property(argumentExpression, propertyName),
                    filterPropertyExpression
                );
    
                var nullCheckExpression = Expression.Equal(
                    filterPropertyExpression,
                    Expression.Constant(null)
                );
    
                var orExpression = Expression.OrElse(equalExpression, nullCheckExpression);
    
                if (expression == null)
                {
                    expression = orExpression;
                }
                else
                {
                    expression = Expression.AndAlso(expression, orExpression);
                }
            }
    
            var lambda = Expression.Lambda<Func<T, bool>>(expression, argumentExpression);
    
            return dbContext.Entry<T>().Where(lambda).ToList();
        }
    

    如果你有这样的类型T { FirstName, LastName } 和Filter 这样的类{ FirstName } 它将创建以下表达式

    x => x.FirstName == filter.FirstName || filter.FirstName == null
    

    如果你有 T 这样的类型 { FirstName, LastName } 和 Filter 这样的类 { FirstName, LastName } 它将创建以下表达式

    x => (x.FirstName == filter.FirstName || filter.FirstName == null) 
         && (x.LastName == filter.LastName || filter.LastName == null)
    

    这样就可以了,但是还有优化的空间。

    【讨论】:

      猜你喜欢
      • 2021-11-10
      • 1970-01-01
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多