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;
		}