Reputation: 1227
I have dynamic lambda expression tree,I prepare my expression and compile it.
My problem is when I prepare expression something like
MyClass1.Property2.ChildProperty1=="xyz";
if Property2 is null then I take nullrefence error.
public class MyClass1
{
public string Property1{get;set;}
public MyClass2 Property2{get;set;}
}
public class MyClass2
{
public string ChildProperty1{get;set;}
public string ChildProperty2{get;set;}
}
public Func<T, bool> CompileRule<T>(Rule r)
{
...
Func<T, bool> myfunc =Expression.Lambda<Func<T, bool>>(expr, paramUser).Compile();
...
return myfunc;
}
Another function I execute my request like " myfunc(myrequest); "
Is there a generic way to check null control when I preprare my expression in CompileTime,If ParentProperty null then return false for these statement?In compile method I dont have entity ,so I have to prepare statement with check null control
Upvotes: 1
Views: 1056
Reputation: 205629
So you want to create dynamically a body of an expression like this:
Expression<Func<MyClass1, string>> expr =
x => x.Property2?.ChildProperty1;
Unfortunately currently there is not standard Expression
method supporting that. If you try the above, you'll get a compile time error:
Error CS8072 An expression tree lambda may not contain a null propagating operator.
One possible way is to generate a body of an expression like this instead:
Expression<Func<MyClass1, string>> expr =
x => x.Property2 != null ? x.Property2.ChildProperty1 : null;
It's not the exact equivalent, but should work.
Here is a sample snippet which does that dynamically:
string memberPath = ...; // e.g. "Property2.ChildProperty2"
var parameter = Expression.Parameter(typeof(T), "x");
Expression result;
if (memberPath.IndexOf('.') < 0)
result = Expression.PropertyOrField(parameter, memberPath);
else
{
var memberNames = memberPath.Split('.');
var members = new Expression[memberNames.Length];
for (int i = 0; i < memberNames.Length; i++)
members[i] = Expression.PropertyOrField(i > 0 ? members[i - 1] : parameter, memberNames[i]);
result = members[members.Length - 1];
// For non nullable value types, promote the result into the corresponding nullable type
if (result.Type.IsValueType && Nullable.GetUnderlyingType(result.Type) == null)
result = Expression.Convert(result, typeof(Nullable<>).MakeGenericType(result.Type));
var nullResult = Expression.Constant(null, result.Type);
for (int i = members.Length - 2; i >= 0; i--)
{
result = Expression.Condition(
Expression.NotEqual(members[i], Expression.Constant(null)),
result, nullResult);
}
}
At the end, the result
variable contains the expression that you can use for left side of the comparison predicate.
Upvotes: 2