/// <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> /// Returns an expression representing a 'throw' instruction based on the specified <see cref="OperationSupport"/> value. /// </summary> /// <param name="supportValue">The <see cref="OperationSupport"/> value.</param> /// <param name="operation">The operation type.</param> /// <param name="thisValue">The operation left operand.</param> /// <param name="operand">The operation right operand.</param> /// <returns>A <see cref="Expression"/> representing a 'throw' instruction.</returns> private static Expression GetOperationErrorExpression(OperationSupport supportValue, ExpressionType operation, JsonValue thisValue, object operand) { string exceptionMessage; string operandTypeName = operand != null?operand.GetType().FullName : "<null>"; switch (supportValue) { default: case OperationSupport.NotSupported: case OperationSupport.NotSupportedOnJsonType: case OperationSupport.NotSupportedOnValueType: exceptionMessage = SG.GetString(SR.OperatorNotDefinedForJsonType, operation, thisValue.JsonType); break; case OperationSupport.NotSupportedOnOperand: exceptionMessage = SG.GetString(SR.OperatorNotAllowedOnOperands, operation, thisValue.GetType().FullName, operandTypeName); break; } return(Expression.Throw(Expression.Constant(new InvalidOperationException(exceptionMessage)), typeof(object))); }
/// <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)); }