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