I have some Expression<Func<T, bool>> exp
and I need to write a method that would return new expression that represents the original one wrapped in try catch. For example, if original expression looks something like order => order.Product.Name == "Product 1"
but order has no product, I need to return false instead of throwing exception;
Here is my method at the moment, but it throws runtime exception saying 'Expression of type 'System.Func
2[MyClass,System.Boolean]' cannot be used for return type 'System.Boolean'`'
private static Expression<Func<T, bool>> FalseOnException<T>(this Expression<Func<T, bool>> exp)
{
Expression<Func<T, bool>> falseExp = parameter => false;
ParameterExpression parameter = exp.Parameters[0];
var tryExp = Expression.TryCatch(exp, Expression.Catch(typeof(NullReferenceException), falseExp));
return Expression.Lambda<Func<T, bool>>(tryExp.Body, parameter);
}
Where MyClass is T
We can adapt the example from the docs a little and it will work:
Expression<Func<T, bool>> FalseOnNullReferenceException<T>(Expression<Func<T, bool>> exp) {
var parameterExpression = Expression.Parameter(typeof(T));
TryExpression tryCatchExpr =
Expression.TryCatch(
Expression.Invoke(exp, parameterExpression)
,
Expression.Catch(
typeof(NullReferenceException),
Expression.Constant(false, typeof(bool))
)
);
return Expression.Lambda<Func<T, bool>>(tryCatchExpr, parameterExpression);;
}
Quick test:
class Foo {
public string Bar { get; set; }
}
Expression<Func<Foo, bool>> exp = f => f.Bar == "Baz";
//exp.Compile()(null); // throws
var tryCatchExp = FalseOnNullReferenceException(exp);
var compiled = tryCatchExp.Compile();
var foo = new Foo { Bar = "Baz" };
Console.WriteLine(compiled(null)); // false
Console.WriteLine(compiled(foo)); // true