如果类型是数组,则为数组中的每个项应用相同的表达式

时间:2017-03-07 17:08:54

标签: c#

我想在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()函数,实际函数中有更多的检查和条件。

1 个答案:

答案 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));