c# - 如何在 linq 查询中传递表达式列表

标签 c# linq lambda expression

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

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 

        }

最佳答案

这将构建 lambda 表达式,它将与通用类型 TFilter 类之间的属性相交,并比较它们是否相等,同时每个单独的属性对与和条件。

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)

这将完成工作,但还有优化空间。

关于c# - 如何在 linq 查询中传递表达式列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59910676/

相关文章:

c# - 异常 : Ambiguous column name

c# - 如何创建像 Windows IP 地址字段一样的 Masked TextBox

node.js - 我可以使用 lambda :invoke to call AWS Lambda express app?

python - 在 Ruby 中可以像这样使用 Lambdas 吗?

c# - 使用 filterContext.Result 时如何重定向到 Action?

c# - 从 datagridview 写入/更新本地数据库

c# - 访问 JToken 的值时出现异常 - 无法访问 Newtonsoft.Json.Linq.JValue 上的子值

c# - 使用 Linq 还是不使用 Linq - 哪个版本更漂亮?

c# - 在查看 ANTS 分析器时,FirstOrDefault 明显快于 SingleOrDefault

spring - Java 8 和 Spring 3.1