I'm trying to build in Expression Trees equivalent of "?." operator.
var member = Expression.Property(Expression.Property("PropertyObjectName", value.Property),
"PropertyOfObject");
which is: member.PropertyObjectName.PropertyOfObject
which of course will throw Null exception
if PropertyObjectName
is null
which I want to avoid.
Is there any way to build member?.PropertyObjectName?.PropertyOfObject
other then putting there ConditionalExpression
?
You can use my Extension method
public static class ExpressionExtensions
{
public static Expression ElvisOperator(this Expression expression, string propertyOrField)
{
return Expression.Condition(Expression.NotEqual(expression, Expression.Constant(null)),
Expression.PropertyOrField(expression, propertyOrField),
Expression.Constant(null, expression.Type)
);
}
}
this generates something like
IIF((x != null), x.propertyname, null)
Then you can use it like this:
public class TestClass
{
public int FirstProp { get; set; }
public TestClass SecondProp { get; set; }
}
var variable = Expression.Parameter(typeof(TestClass), "x");
var nullSafe = variable.ElvisOperator("SecondProp");
I made this test:
List<TestClass> tests = new List<TestClass>(){
new TestClass() { FirstProp = 1, SecondProp = new TestClass() { SecondProp = new TestClass() } },
new TestClass() { FirstProp = 2 },
new TestClass() { FirstProp = 3, SecondProp = new TestClass() },
new TestClass() { FirstProp = 4 },
};
var variable = Expression.Parameter(typeof(TestClass), "x");
var nullSafe = variable.ElvisOperator("SecondProp").ElvisOperator("SecondProp");
var cond = Expression.NotEqual(nullSafe, Expression.Constant(null, variable.Type));
var lambda = Expression.Lambda<Func<TestClass, bool>>(cond, new ParameterExpression[] { variable });
tests = tests.AsQueryable().Where(lambda).ToList();
Console.WriteLine(tests.Count);
This prints 1 on the console because filters the list like this:
.Where(x => x.SecondProp?SecondProp != null)