Example #1
0
        /// <summary>
        /// Implements setter for dynamic indexer by index (JsonArray)
        /// </summary>
        /// <param name="binder">An instance of the <see cref="GetIndexBinder"/> that represents the details of the dynamic operation.</param>
        /// <param name="indexes">An array of <see cref="DynamicMetaObject"/> instances - indexes for the get index operation.</param>
        /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)
        {
            if (binder == null)
            {
                throw new ArgumentNullException("binder");
            }

            if (indexes == null)
            {
                throw new ArgumentNullException("indexes");
            }

            Expression indexExpression;

            if (!JsonValueDynamicMetaObject.TryGetIndexExpression(indexes, out indexExpression))
            {
                return(new DynamicMetaObject(indexExpression, DefaultRestrictions));
            }

            MethodInfo methodInfo = indexExpression.Type == typeof(string) ? _getValueByKeyMethodInfo : _getValueByIndexMethodInfo;

            Expression[] args = new Expression[] { indexExpression };

            return(GetMethodMetaObject(methodInfo, args));
        }
        /// <summary>
        /// Performs the binding of the dynamic unary operation.
        /// </summary>
        /// <param name="binder">An instance of the <see cref="UnaryOperationBinder"/> that represents the details of the dynamic operation.</param>
        /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject BindUnaryOperation(UnaryOperationBinder binder)
        {
            if (binder == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binder"));
            }

            Expression operExpression = null;
            JsonValue  jsonValue      = this.Value as JsonValue;

            if (jsonValue is JsonPrimitive)
            {
                OperationSupport supportValue = GetUnaryOperationSupport(binder.Operation, jsonValue);

                if (supportValue == OperationSupport.Supported)
                {
                    Type operationReturnType = this.GetUnaryOperationReturnType(binder);

                    Expression instance       = Expression.Convert(this.Expression, this.LimitType);
                    Expression thisExpression = Expression.Convert(Expression.Call(instance, ReadAsMethodInfo, new Expression[] { Expression.Constant(operationReturnType) }), operationReturnType);

                    operExpression = JsonValueDynamicMetaObject.GetUnaryOperationExpression(binder.Operation, thisExpression);
                }
            }

            if (operExpression == null)
            {
                operExpression = JsonValueDynamicMetaObject.GetOperationErrorExpression(OperationSupport.NotSupportedOnJsonType, binder.Operation, jsonValue, null);
            }

            operExpression = Expression.Convert(operExpression, binder.ReturnType);

            return(new DynamicMetaObject(operExpression, this.DefaultRestrictions));
        }
        /// <summary>
        /// Updates the <see cref="Expression"/> tree for the operands of the specified operation.
        /// </summary>
        /// <param name="operation">The operation to evalutes.</param>
        /// <param name="thisOperand">The first operand.</param>
        /// <param name="otherOperand">The second operand.</param>
        /// <param name="thisExpression">The <see cref="Expression"/> for the first operand.</param>
        /// <param name="otherExpression">The <see cref="Expression"/> for the second operand.</param>
        private static void GetBinaryOperandExpressions(ExpressionType operation, DynamicMetaObject thisOperand, DynamicMetaObject otherOperand, ref Expression thisExpression, ref Expression otherExpression)
        {
            JsonValue thisValue  = thisOperand.Value as JsonValue;
            JsonValue otherValue = otherOperand.Value as JsonValue;

            Type thisType  = thisValue.Read().GetType();
            Type otherType = otherValue != null?otherValue.Read().GetType() : otherOperand.Value.GetType();

            Type coercedType;

            if (JsonValueDynamicMetaObject.TryCoerceType(operation, thisType, otherType, out coercedType))
            {
                thisType = otherType = coercedType;
            }
            else if (JsonValueDynamicMetaObject.TryCoerceSpecialTypes(thisOperand, otherOperand, out coercedType))
            {
                thisType = otherType = coercedType;
            }

            thisExpression = Expression.Convert(thisExpression, thisOperand.LimitType);
            thisExpression = Expression.Convert(Expression.Call(thisExpression, ReadAsMethodInfo, new Expression[] { Expression.Constant(thisType) }), thisType);

            otherExpression = Expression.Convert(otherExpression, otherOperand.LimitType);
            if (otherValue != null)
            {
                otherExpression = Expression.Convert(Expression.Call(otherExpression, ReadAsMethodInfo, new Expression[] { Expression.Constant(otherType) }), otherType);
            }
            else if (otherOperand.LimitType != otherType)
            {
                otherExpression = Expression.Convert(otherExpression, otherType);
            }
        }
        /// <summary>
        /// Implements getter for dynamic indexer by index (JsonArray).
        /// </summary>
        /// <param name="binder">An instance of the <see cref="SetIndexBinder"/> that represents the details of the dynamic operation.</param>
        /// <param name="indexes">An array of <see cref="DynamicMetaObject"/> instances - indexes for the set index operation.</param>
        /// <param name="value">The <see cref="DynamicMetaObject"/> representing the value for the set index operation.</param>
        /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)
        {
            if (binder == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binder"));
            }

            if (indexes == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("indexes"));
            }

            if (value == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value"));
            }

            Expression indexExpression;

            if (!JsonValueDynamicMetaObject.TryGetIndexExpression(indexes, out indexExpression))
            {
                return(new DynamicMetaObject(indexExpression, this.DefaultRestrictions));
            }

            MethodInfo methodInfo = indexExpression.Type == typeof(string) ? SetValueByKeyMethodInfo : SetValueByIndexMethodInfo;

            Expression[] args = new Expression[] { indexExpression, Expression.Convert(value.Expression, typeof(object)) };

            return(this.GetMethodMetaObject(methodInfo, args));
        }
Example #5
0
        /// <summary>
        /// Performs the binding of the dynamic invoke member operation.
        /// Implemented to support extension methods defined in <see cref="JsonValueExtensions"/> type.
        /// </summary>
        /// <param name="binder">An instance of the InvokeMemberBinder that represents the details of the dynamic operation.</param>
        /// <param name="args">An array of DynamicMetaObject instances - arguments to the invoke member operation.</param>
        /// <returns>The new DynamicMetaObject representing the result of the binding.</returns>
        public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
        {
            if (binder == null)
            {
                throw new ArgumentNullException("binder");
            }

            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            List <Type> argTypeList = new List <Type>();

            for (int idx = 0; idx < args.Length; idx++)
            {
                argTypeList.Add(args[idx].LimitType);
            }

            MethodInfo methodInfo = Value.GetType().GetMethod(binder.Name, argTypeList.ToArray());

            if (methodInfo == null)
            {
                argTypeList.Insert(0, typeof(JsonValue));

                Type[] argTypes = argTypeList.ToArray();

                methodInfo = JsonValueDynamicMetaObject.GetExtensionMethod(typeof(JsonValueExtensions), binder.Name, argTypes);

                if (methodInfo != null)
                {
                    Expression   thisInstance   = Expression.Convert(Expression, LimitType);
                    Expression[] argsExpression = new Expression[argTypes.Length];

                    argsExpression[0] = thisInstance;
                    for (int i = 0; i < args.Length; i++)
                    {
                        argsExpression[i + 1] = args[i].Expression;
                    }

                    Expression callExpression = Expression.Call(methodInfo, argsExpression);

                    if (methodInfo.ReturnType == typeof(void))
                    {
                        callExpression = Expression.Block(callExpression, Expression.Default(binder.ReturnType));
                    }
                    else
                    {
                        callExpression = Expression.Convert(Expression.Call(methodInfo, argsExpression), binder.ReturnType);
                    }

                    return(new DynamicMetaObject(callExpression, DefaultRestrictions));
                }
            }

            return(base.BindInvokeMember(binder, args));
        }
        /// <summary>
        /// Performs the binding of the dynamic binary operation.
        /// </summary>
        /// <param name="binder">An instance of the <see cref="BinaryOperationBinder"/> that represents the details of the dynamic operation.</param>
        /// <param name="arg">An instance of the <see cref="DynamicMetaObject"/> representing the right hand side of the binary operation.</param>
        /// <returns>The new <see cref="DynamicMetaObject"/> representing the result of the binding.</returns>
        public override DynamicMetaObject BindBinaryOperation(BinaryOperationBinder binder, DynamicMetaObject arg)
        {
            if (binder == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binder"));
            }

            if (arg == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("arg"));
            }

            Expression thisExpression  = this.Expression;
            Expression otherExpression = arg.Expression;
            Expression operExpression  = null;

            JsonValue otherValue = arg.Value as JsonValue;
            JsonValue thisValue  = this.Value as JsonValue;

            OperationSupport supportValue = JsonValueDynamicMetaObject.GetBinaryOperationSupport(binder.Operation, thisValue, arg.Value);

            if (supportValue == OperationSupport.Supported)
            {
                if (otherValue != null)
                {
                    if (thisValue is JsonPrimitive && otherValue is JsonPrimitive)
                    {
                        //// operation on primitive types.

                        JsonValueDynamicMetaObject.GetBinaryOperandExpressions(binder.Operation, this, arg, ref thisExpression, ref otherExpression);
                    }
                    else
                    {
                        //// operation on JsonValue types.

                        thisExpression  = Expression.Convert(thisExpression, typeof(JsonValue));
                        otherExpression = Expression.Convert(otherExpression, typeof(JsonValue));
                    }
                }
                else
                {
                    if (arg.Value != null)
                    {
                        //// operation on JSON primitive and CLR primitive

                        JsonValueDynamicMetaObject.GetBinaryOperandExpressions(binder.Operation, this, arg, ref thisExpression, ref otherExpression);
                    }
                    else
                    {
                        //// operation on JsonValue and null.

                        thisExpression = Expression.Convert(thisExpression, typeof(JsonValue));

                        if (thisValue.JsonType == JsonType.Default)
                        {
                            thisExpression = Expression.Constant(null);
                        }
                    }
                }

                operExpression = JsonValueDynamicMetaObject.GetBinaryOperationExpression(binder.Operation, thisExpression, otherExpression);
            }

            if (operExpression == null)
            {
                operExpression = JsonValueDynamicMetaObject.GetOperationErrorExpression(supportValue, binder.Operation, thisValue, arg.Value);
            }

            operExpression = Expression.Convert(operExpression, typeof(object));

            return(new DynamicMetaObject(operExpression, this.DefaultRestrictions));
        }