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



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

这就是我这样做的方式。更改为Funcion返回结果而不是表达式

 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)上的"任何"

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

最新更新