动态 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; }
    }
}

您应该能够查看评论并以此作为构建动态表达式的示例