表达式树:如何检查索引是否存在?

时间:2017-02-27 13:44:19

标签: c#

我正在编写表达式树来验证Json对象。这是检查是否stuff["Address"]["State"]== "NY"

var stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

ParameterExpression parameterExpression = Expression.Parameter(typeof(JObject), "g");
var indexexpr = Expression.MakeIndex(parameterExpression, typeof(JObject).GetProperty("Item", new[] { typeof(string) }), new[] { Expression.Constant("Address") });
var secondlevel = Expression.MakeIndex(indexexpr, typeof(JToken).GetProperty("Item", new[] { typeof(string) }), new[] { Expression.Constant("State") });

var conversion = Expression.Convert(secondlevel, typeof(string));

var result = Expression.Equal(conversion, Expression.Constant("NY"));

var fun =Expression.Lambda<Func<JObject, bool>>(result, new[] {parameterExpression}).Compile();
var istrue = fun(stuff);

问题:对于json对象,有时索引不存在。例如,如果我对同一个对象执行stuff["Home Address"]["State"]== "NY",则表达式将抛出异常

问题:如何在尝试评估索引属性之前检查索引属性是否存在?

1 个答案:

答案 0 :(得分:3)

基本上你需要的是:

(string) (stuff["Address"] != null ? stuff["Address"]["State"] : (JToken) null) == "NY"

这可以这样构建:

var stuff = JObject.Parse("{ 'Name': 'Jon Smith', 'Address': { 'City': 'New York', 'State': 'NY' }, 'Age': 42 }");

ParameterExpression parameterExpression = Expression.Parameter(typeof(JObject), "g");
var indexexpr = Expression.MakeIndex(parameterExpression, typeof(JObject).GetProperty("Item", new[] { typeof(string) }),
            new[] { Expression.Constant("Address2") });                                    
var secondlevel = Expression.MakeIndex(indexexpr, typeof(JToken).GetProperty("Item", new[] { typeof(string) }),
           new[] { Expression.Constant("State") });

// stuff["Address2"] != null
var nullCheck = Expression.NotEqual(indexexpr, Expression.Constant(null, typeof(object)));
// stuff["Address2"] != null ? stuff["Address2"]["State"] : (JToken) null
var finalExpression = Expression.Condition(nullCheck, secondlevel, Expression.Default(typeof(JToken)));
// (string) (stuff["Address2"] != null ? stuff["Address2"]["State"] : (JToken) null)
var conversion = Expression.Convert(finalExpression, typeof(string));
// final expression
var result = Expression.Equal(conversion, Expression.Constant("NY"));

var fun = Expression.Lambda<Func<JObject, bool>>(result, new[] { parameterExpression }).Compile();            
var istrue = fun(stuff);