Ich habe diesen Code, in dem eine Datenbank-DDL zur Laufzeit in Dynamic Linq umgewandelt wird, um einen Filter zu definieren. Der Code funktioniert, außer dass einige Filter auf eine untergeordnete Eigenschaft verweisen, die null sein kann. Wenn die Regel angewendet wird, führt die Null dazu, dass die gesamte Anweisung explodiert.
Als Beispiel:
// 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
Da ich das Objekt und den Filter (hier als filterExpression definiert) zur Laufzeit erhalte, brauche ich eine Möglichkeit, der Linq-Sequenz zu entkommen, wenn die Null-Eigenschaft gefunden wird. Leider scheint das Hinzufügen der Null-Prüfung nicht geholfen zu haben, da die filterExpression unabhängig vom Ergebnis der nullExpression explodiert. Ich bin mir nicht sicher, ob ich den dynamischen Linq falsch geschrieben habe oder ob es einen anderen Weg gibt, dies zu tun. Irgendwelche Ideen?
Die Ausnahme :
System.NullReferenceException: Object reference not set to an instance of an object.
at lambda_method(Closure , ParentObject )
Überprüfen Sie den folgenden Unit-Test, der als Proof of Concept verwendet wird.
[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; }
}
}
Sie sollten in der Lage sein, sich die Kommentare anzusehen und diese als Beispiel zu verwenden, wenn der dynamische Ausdruck erstellt wird