动态 Linq 不能容忍 null 属性
Dynamic Linq not tolerating null property
我有这段代码,其中数据库 DDL 在运行时转换为 Dynamic Linq 以定义 filter.The 代码有效,除了一些过滤器引用可以为 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 属性,我需要一些方法来 'escape' Linq 序列。不幸的是,添加 Null 检查似乎没有帮助,因为无论 nullExpression 的结果如何,filterExpression 都会爆炸。我不确定我是否将动态 Linq 写错了,或者是否有另一种方法可以解决这个问题。有什么想法吗?
异常:
System.NullReferenceException: Object reference not set to an instance of an object.
at lambda_method(Closure , ParentObject )
查看以下用作概念证明的单元测试。
[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; }
}
}
您应该能够查看评论并以此作为构建动态表达式的示例
我有这段代码,其中数据库 DDL 在运行时转换为 Dynamic Linq 以定义 filter.The 代码有效,除了一些过滤器引用可以为 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 属性,我需要一些方法来 'escape' Linq 序列。不幸的是,添加 Null 检查似乎没有帮助,因为无论 nullExpression 的结果如何,filterExpression 都会爆炸。我不确定我是否将动态 Linq 写错了,或者是否有另一种方法可以解决这个问题。有什么想法吗?
异常:
System.NullReferenceException: Object reference not set to an instance of an object.
at lambda_method(Closure , ParentObject )
查看以下用作概念证明的单元测试。
[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; }
}
}
您应该能够查看评论并以此作为构建动态表达式的示例