我有这样的代码,其中数据库DDL在运行时被转换为Dynamic Linq以定义过滤器。除了一些过滤器引用可以为null的子属性之外,代码有效。应用规则时,null会导致整个语句爆炸。
举个例子:
// filter is to see if ParentObject.ChildObject.ChildProperty > 1
var param = Expression.Parameter(typeof(ParentObject));
var nullExpression = Expression.NotEqual(Expression.PropertyOrField(param, "ChildObject"), Expression.Constant(null));
var propertyExpression = Expression.Constant(ChildProperty);
var filterExpression = Expression.MakeBinary(ExpressionType.GreaterThan, propertyExpression, typeof(ChildObject));
var finalExpression = Expression.Add({nullExpression, propertyExpression});
var compiledExpression = Expression.Lambda<Func<T, bool>>(finalExpression, param).Compile() //Compilation will succeed
var isTrue = compiledExpression(ParentObject); //If ChildObject is null, this will explode
由于我在运行时收到对象和过滤器(此处定义为filterExpression),因此如果找到Null属性,我需要一些方法来“转义”Linq序列。不幸的是,添加Null检查似乎没有帮助,因为无论nullExpression的结果如何,filterExpression都会爆炸。我不确定我是否写了动态Linq错误或者是否有其他方法可以解决这个问题。有什么想法吗?
例外:
System.NullReferenceException: Object reference not set to an instance of an object.
at lambda_method(Closure , ParentObject )
答案 0 :(得分:2)
查看以下用作概念证明的单元测试。
[TestClass]
public class UnitTest5 {
[TestMethod]
public void _MyTestMethod1() {
var target = new ParentObject {
ChildObject = new ChildObject {
ChildProperty = 5
}
};
Assert.IsTrue(TestMethod1(target));
}
[TestMethod]
public void _MyTestMethod2() {
var target = new ParentObject {
};
Assert.IsFalse(TestMethod1(target));
}
public bool TestMethod1<T>(T ParentObject) {
// filter is to see if ParentObject.ChildObject.ChildProperty > 1
// p => p.ChildObject != null && p.ChildObject.ChildProperty > 1
// p => ...
var param = Expression.Parameter(typeof(T));
// p => p.ChildObject
var childObjectExpression = Expression.PropertyOrField(param, "ChildObject");
// p => p.ChildObject != null
var nullExpression = Expression.NotEqual(childObjectExpression, Expression.Constant(null));
// p => p.ChildObject.ChildProperty
var childPropertyExpression = Expression.Property(childObjectExpression, "ChildProperty");
// p => p.ChildObject.ChildProperty > 1
var greaterThanExpression = Expression.MakeBinary(ExpressionType.GreaterThan, childPropertyExpression, Expression.Constant(1));
// p => p.ChildObject != null && p.ChildObject.ChildProperty > 1
var finalExpression = Expression.AndAlso(nullExpression, greaterThanExpression);
var compiledExpression = Expression.Lambda<Func<T, bool>>(finalExpression, param).Compile();//Compilation will succeed
var isTrue = compiledExpression(ParentObject);
return isTrue;
}
public class ParentObject {
public ChildObject ChildObject { get; set; }
}
public class ChildObject {
public int ChildProperty { get; set; }
}
}
您应该能够查看注释并将其用作构建动态表达式的示例