通过迭代对象属性生成动态LINQ表达式 [英] Generate Dynamic LINQ Expression By Iterating object properties
本文介绍了通过迭代对象属性生成动态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屋!
查看全文