通过迭代对象属性生成动态LINQ表达式 [英] Generate Dynamic LINQ Expression By Iterating object properties

查看:53
本文介绍了通过迭代对象属性生成动态LINQ表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图遍历对象中的所有属性,包括嵌套对象和集合中的对象,以生成LINQ表达式.我的课程结构如下:

I am trying to loop through all properties in an object including nested objects and objects in collections to generate LINQ expressions. The structure of my classes as follows:

public class Rule
{
    public string label { get; set; }
    public string field { get; set; }
    public string @operator { get; set; }
    public string type { get; set; }
    public string value { get; set; }
    public string condition { get; set; }
    public List<Rule> rules { get; set; }
}
public class QueryBuilder
{

    public string condition { get; set; }
    public List<Rule> rules { get; set; }

}

bellow是上述实体映射的示例JSON

bellow is the example JSON for the above entity mapping

{
"condition": "and",
"rules": [
    {
        "condition": "or",
        "rules": [
            {
                "label": "PaymentMode",
                "field": "PaymentMode",
                "operator": "equal",
                "type": "string",
                "value": "Cash"
            },
            {
                "label": "TransactionType",
                "field": "TransactionType",
                "operator": "equal",
                "type": "string",
                "value": "expensive"
            }
        ]
    },
    {
        "condition": "or",
        "rules": [
            {
                "label": "Date",
                "field": "Date",
                "operator": "equal",
                "type": "date",
                "value": "4/15/21"
            },
            {
                "label": "Date",
                "field": "Date",
                "operator": "equal",
                "type": "date",
                "value": "4/15/21"
            }
        ]
    }
]
}

上面的json将处于层次结构中.用户可以选择任意数量的与"或或"条件.需要在递归循环中进行波纹管表达式

The above json will be in a hierarchy. User can select any number of AND or OR condition. Need to make bellow expression inside a recursive loop

var constant = Expression.Constant("Jhon");
              var property = Expression.Property(paramExpr,"FirstName");
              expression = Expression.Equal(property, constant);

              constant = Expression.Constant("Ram");
              property = Expression.Property(paramExpr, "LastName");
              var expression2 = Expression.Equal(property, constant);
              expression = Expression.Or(expression, expression2);

如何使用上述结构进行递归循环.

How can I make a recursive loop with the above structure.

推荐答案

应该执行以下操作:

    public Expression BuildExpression(ParameterExpression paramExpr, Rule rule)
    {
        if (rule.condition != null)
        {
            if (rule.condition != "or" && rule.condition != "and")
                throw new Exception($"Condition [{rule.condition}] is invalid.");

            if (rule.rules == null || rule.rules.Count < 2)
                throw new Exception($"Cannot create [{rule.condition}] expression.");

            IList<Expression> expressions = rule.rules
                .Select(rule => BuildExpression(paramExpr, rule))
                .ToList();

            if (rule.condition == "or")
                return JoinExpressions(expressions, (left, right) => Expression.OrElse(left, right));
            else
                return JoinExpressions(expressions, (left, right) => Expression.AndAlso(left, right));
        }
        else
        {
            Expression constant = Expression.Constant(rule.value);
            Expression property = Expression.Property(paramExpr, rule.field);

            // added to allow any value to be included.
            if (rule.value == "ANY")
            {
                Type type = GetType(rule.type);
                if (!type.IsPrimitive)
                {
                    constant = Expression.Constant(null, type);

                    switch (rule.@operator)
                    {
                        case "equal": return Expression.NotEqual(property, constant);
                        case "notequal": return Expression.Equal(property, constant);
                        default:
                            throw new Exception($"Operator [{rule.@operator}] is invalid for ANY filter. Use only equal or notequal.");
                    }
                }

                constant = property;
            }

            switch (rule.@operator)
            {
                case "equal": return Expression.Equal(property, constant);
                case "notequal": return Expression.NotEqual(property, constant);
                case "greaterthan": return Expression.GreaterThan(property, constant);
                case "greaterthanorequal": return Expression.GreaterThanOrEqual(property, constant);
                case "lessthan": return Expression.LessThan(property, constant);
                case "lessthanorequal": return Expression.LessThanOrEqual(property, constant);
                default:
                    throw new Exception($"Operator [{rule.@operator}] is invalid.");
            }
        }
    }

    public Expression JoinExpressions(IList<Expression> expressions, Func<Expression, Expression, Expression> join)
    {
        Expression andExpression = null;

        foreach (Expression expression in expressions)
        {
            if (andExpression == null)
                andExpression = expression;
            else
                andExpression = join(andExpression, expression);
        }

        return andExpression;
    }

    public static Type GetType(string typeName)
    {
        switch (typeName)
        {
            case "string": return typeof(string);
            ... add any others.
            default:
                throw new Exception($"Type [{typeName}] is invalid.");
        }
    }

这篇关于通过迭代对象属性生成动态LINQ表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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