Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expression Tree C# - Null-Conditional oeprator (?.) [duplicate]

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?

like image 455
nilphilus Avatar asked Aug 18 '26 14:08

nilphilus


1 Answers

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)
like image 146
aperezfals Avatar answered Aug 21 '26 04:08

aperezfals