我想在JSON对象上应用过滤条件
因此,我创建了一个表达式树来按名称访问JSON节点,然后在其上应用转换/解析和BinaryOperation
。
var stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Tags': ['Developer', 'Scrum Master'], 'Age': 42, }");
var leftExpressionTree = GetLeftExpressionTree("Name", stuff)
var binaryExpression = DoExpression(leftExpressionTree, "Jon Smith", ExpressionType.Equal)
//Complie and execute expression
public static Expression DoExpression(Expression leftExpression, string rightOperandStr, ExpressionType expressionType)
{
var leftExpressionConversionfromJtokenToString = Expression.Convert(leftExpression, typeof(string));
var rightExpression = Expression.Call(GetParseMethodForType(rightOperandStr), Expression.Constant(rightOperandStr));
var binaryExpression = Expression.MakeBinary(expressionType, leftExpressionConversionfromJtokenToString, rightExpression);
return binaryExpression;
}
没关系,"姓名"是一个字符串类型,它的工作原理
但是,当我执行以下操作时会出现问题:
var leftExpressionTree = GetLeftExpressionTree("Tags")
var binaryExpression = DoExpression(leftExpressionTree, "Scrum Master", ExpressionType.Equal)
这不起作用,因为标签是JArray
。
当它是array
时的预期行为是,条件必须应用于所有数组项,并且过滤器将通过任何条件
因此,必须为数组中的每个项执行DoExpression
中编写的任何代码。
我怎么能这样做?请注意,为简单起见,我简化了DoExpression()
函数,实际函数中有更多的检查和条件。
答案 0 :(得分:0)
我是这样做的。将DoExpression更改为返回结果的函数而不是表达式
public static bool DoAction(JToken token, string rightOperand, ExpressionType type)
{
var str = (string) token;
var tokenExpr = Expression.Parameter(typeof(object));
var strExpr = Expression.Parameter(typeof(object));
var expr = Expression.MakeBinary(type, tokenExpr, strExpr);
var compiledExpr = Expression.Lambda<Func<object, object, bool>>(expr, tokenExpr, strExpr).Compile();
return compiledExpr(str, rightOperand);
}
在对象(JArray)上调用可枚举“Any”的函数
public static Expression GetArrayExpression(Expression leftExpression)
{
Type predType = typeof(Func<,>).MakeGenericType(typeof(JToken), typeof(bool));
MethodInfo anyMethod = (MethodInfo)GetGenericMethod(typeof(Enumerable), "Any", new[] { typeof(JToken) }, new[] { typeof(JArray), predType }, BindingFlags.Static);
MethodInfo miDoAction = typeof(Program).GetMethod("DoAction", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
ParameterExpression p = Expression.Parameter(typeof(JToken), "item");
var callExpr1 = Expression.Lambda<Func<JToken, bool>>(Expression.Call(miDoAction, p, Expression.Constant("SearchForThis"), Expression.Constant(ExpressionType.Equal)), p);
var callExpr = Expression.Call(anyMethod, leftExpression, callExpr1);
return callExpr;
}
如果函数是对象则调用函数的函数
public static Expression GetObjectExpression(Expression leftExpression)
{
MethodInfo miDoAction = typeof(Program).GetMethod("DoAction", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);
var callExpr = Expression.Call(miDoAction, leftExpression, Expression.Constant("SearchForThis"), Expression.Constant(ExpressionType.Equal));
return callExpr;
}
然后这只是条件调用的问题
Expression leftExpression;
var isTypeJarray = Expression.TypeIs(leftExpression, typeof(JArray));
return Expression.Condition(isTypeJarray, GetArrayExpression(leftExpression), GetObjectExpression(leftExpression));