namespace GenericImage.Helpers { using System; using System.Linq.Expressions; /// /// General purpose Expression utilities /// public static class ExpressionUtil { /// /// Create a function delegate representing a unary operation /// /// The parameter type /// The return type /// Body factory /// Compiled function delegate public static Func CreateExpression( Func body) { ParameterExpression inp = Expression.Parameter(typeof(TArg1), "inp"); try { return Expression.Lambda>(body(inp), inp).Compile(); } catch (Exception ex) { string msg = ex.Message; // avoid capture of ex itself return delegate { throw new InvalidOperationException(msg); }; } } /// /// Create a function delegate representing a binary operation /// /// The first parameter type /// The second parameter type /// The return type /// Body factory /// Compiled function delegate public static Func CreateExpression( Func body) { return CreateExpression(body, false); } /// /// Create a function delegate representing a binary operation /// /// /// If no matching operation is possible, attempt to convert /// TArg1 and TArg2 to TResult for a match? For example, there is no /// "decimal operator /(decimal, int)", but by converting TArg2 (int) to /// TResult (decimal) a match is found. /// /// The first parameter type /// The second parameter type /// The return type /// Body factory /// Compiled function delegate public static Func CreateExpression( Func body, bool castArgsToResultOnFailure) { ParameterExpression lhs = Expression.Parameter(typeof(TArg1), "lhs"); ParameterExpression rhs = Expression.Parameter(typeof(TArg2), "rhs"); try { try { return Expression.Lambda>(body(lhs, rhs), lhs, rhs).Compile(); } catch (InvalidOperationException) { // If we show retry and the args aren't already "TValue, TValue, TValue"... // convert both lhs and rhs to TResult (as appropriate) if (castArgsToResultOnFailure && !(typeof(TArg1) == typeof(TResult) && typeof(TArg2) == typeof(TResult))) { Expression castLhs = typeof(TArg1) == typeof(TResult) ? lhs : (Expression)Expression.Convert(lhs, typeof(TResult)); Expression castRhs = typeof(TArg2) == typeof(TResult) ? rhs : (Expression)Expression.Convert(rhs, typeof(TResult)); return Expression.Lambda>( body(castLhs, castRhs), lhs, rhs).Compile(); } throw; } } catch (Exception ex) { string msg = ex.Message; // avoid capture of ex itself return delegate { throw new InvalidOperationException(msg); }; } } } }