public override DynamicMetaObject BindInvokeMember(
			InvokeMemberBinder binder, DynamicMetaObject[] args)
		{
			var expressionFunctionConstructor = typeof(ExpressionFunction).GetConstructor(new[] { typeof(string), typeof(IEnumerable<object>) });
			if (FunctionMapping.ContainsFunction(binder.Name, args.Length))
			{
				var expression = Expression.New(CtorWithExpressionAndExpressionFunction,
					Expression.Convert(Expression, LimitType),
					Expression.New(expressionFunctionConstructor,
						Expression.Constant(binder.Name),
						Expression.NewArrayInit(typeof(object), args.Select(x => Expression.Convert(x.Expression, typeof(object))))));

				return new DynamicMetaObject(
					expression,
					BindingRestrictions.GetTypeRestriction(Expression, LimitType));
			}

			if (string.Equals(binder.Name, ODataLiteral.Any, StringComparison.OrdinalIgnoreCase) ||
				string.Equals(binder.Name, ODataLiteral.All, StringComparison.OrdinalIgnoreCase))
			{
				var expression = Expression.New(CtorWithExpressionAndExpressionFunction,
					Expression.Convert(Expression, LimitType),
					Expression.New(expressionFunctionConstructor,
						Expression.Constant(binder.Name),
						Expression.NewArrayInit(typeof(object), args.Select(x => Expression.Convert(x.Expression, typeof(object))))));

				return new DynamicMetaObject(
					expression,
					BindingRestrictions.GetTypeRestriction(Expression, LimitType));
			}

			if (string.Equals(binder.Name, ODataLiteral.IsOf, StringComparison.OrdinalIgnoreCase) ||
				string.Equals(binder.Name, ODataLiteral.Is, StringComparison.OrdinalIgnoreCase) ||
				string.Equals(binder.Name, ODataLiteral.Cast, StringComparison.OrdinalIgnoreCase) ||
				string.Equals(binder.Name, ODataLiteral.As, StringComparison.OrdinalIgnoreCase))
			{
				var functionName = string.Equals(binder.Name, ODataLiteral.Is, StringComparison.OrdinalIgnoreCase)
					? ODataLiteral.IsOf
					: string.Equals(binder.Name, ODataLiteral.As, StringComparison.OrdinalIgnoreCase)
						? ODataLiteral.Cast
						: binder.Name;

				var isNullProperty = typeof(DynamicODataExpression).GetProperty(nameof(IsNull));
				var expressionFunctionArguments = Expression.Condition(Expression.MakeMemberAccess(Expression.Convert(Expression, LimitType), isNullProperty),
					Expression.Convert(Expression, typeof(object)),
					Expression.Convert(args.First().Expression, typeof(object)));

				var expression = Expression.New(CtorWithExpressionAndExpressionFunction,
					Expression.Convert(Expression, LimitType),
					Expression.New(expressionFunctionConstructor,
						Expression.Constant(functionName),
						Expression.NewArrayInit(typeof(object), expressionFunctionArguments)));

				return new DynamicMetaObject(
					expression,
					BindingRestrictions.GetTypeRestriction(Expression, LimitType));
			}

			return base.BindInvokeMember(binder, args);
		}
		public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
		{
			ConstructorInfo ctor;
			Expression[] ctorArguments;
			if (FunctionMapping.ContainsFunction(binder.Name, 0))
			{
				ctor = CtorWithExpressionAndString;
				ctorArguments = new Expression[] { Expression.Convert(Expression, LimitType), Expression.Constant(binder.Name) };
			}
			else
			{
				Expression<Func<bool, ODataExpression, string>> calculateReference = (hv, e) => hv && !string.IsNullOrEmpty(e.Reference)
					? string.Join("/", e.Reference, binder.Name)
					: binder.Name;
				var referenceExpression = Expression.Invoke(calculateReference, Expression.Constant(HasValue), Expression.Convert(Expression, LimitType));
				ctor = CtorWithString;
				ctorArguments = new Expression[] { referenceExpression };
			}

			return new DynamicMetaObject(
				Expression.New(ctor, ctorArguments),
				BindingRestrictions.GetTypeRestriction(Expression, LimitType));
		}