public static Maybe<object> Evaluate(Expression argument) { var value = argument.MaybeAs<ConstantExpression>().Select(x => x.Value) .OrElse(() => from memberExpression in argument.MaybeAs<MemberExpression>() from @object in memberExpression.Expression.MaybeAs<ConstantExpression>(nullMeansNothing: false) from computedValue in memberExpression.Member.MaybeAs<PropertyInfo>().Select(x => x.GetValue(@object.Value, null)) .OrElse(() => memberExpression.Member.MaybeAs<FieldInfo>().Select(x => x.GetValue(@object.Value))) select computedValue ); return value; }
public static Maybe<object> SimpleEval(Expression lambdaContainer) { Maybe<object> lambda = from methodCallExpression in lambdaContainer.MaybeAs<MethodCallExpression>() from @object in methodCallExpression.Object.MaybeAs<ConstantExpression>(nullMeansNothing: false) from parameters in GetParameters(methodCallExpression) from lambdaExpression in Maybe.Just(methodCallExpression.Method.Invoke(@object == null ? null : @object.Value, parameters.ToArray())) select lambdaExpression; Maybe<object> maybe = lambda.OrElse(() => Evaluate(lambdaContainer)); return maybe; }
private static Maybe<string> GetMethodName(Expression expr) { return expr.MaybeAs<MethodCallExpression>().Bind( call => { if (call.Arguments.Count == 0 || (call.Method.IsExtensionMethod() && call.Arguments.Count == 1)) { return Maybe.Just(call.Method.Name); } return Maybe.Nothing; } ); }
// special case for protected nullable properties // for x==null?null:(Nullable<T>)Expr(x) returns name of Expr(x) private Maybe<string> GetConditionName(Expression expr, int exprPos) { return expr.MaybeAs<ConditionalExpression>() .Bind(conditional => ExtensionsProvider.GetValue<Expression>(conditional) .Bind(x => GetPropertyName(x, exprPos))); }
// find the root of Enumerable chains and get it name // userstories.Where(x).select(y)=>'userstories' private Maybe<string> GetEnumerableRootName(Expression expr, int exprPos) { return expr.MaybeAs<MethodCallExpression>() .Where(x => x.Method.DeclaringType == typeof(Enumerable)) .Where(x => !AggregationMethodNames.Contains(x.Method.Name)) .Select(x => x.Arguments.First()) .Bind(x => GetPropertyName(x, exprPos)); }
private Maybe<string> GetPropertyName(Expression expr, int exprPos) { var maybePropName = expr .MaybeAs<MemberExpression>().Select(x => x.Member.Name) .OrElse(() => DynamicDictionary.GetAlias(expr, exprPos)) .OrElse(() => GetConditionName(expr, exprPos)) .OrElse(() => GetEnumerableRootName(expr, exprPos)) .OrElse(() => GetMethodName(expr)); return maybePropName; }