/// <summary> /// Attempts to coerce the operand types on a binary operation for some special type and value cases as treated by JsonValue: /// "true" and "false" can be converted to boolean. /// Guid, DateTime and other types can be converted to string. /// </summary> /// <param name="thisOperand">The first operand.</param> /// <param name="otherOperand">The second operand</param> /// <param name="coercedType">On success, this parameter contains the coerced type.</param> /// <returns>true if the coercion is performed, false otherwise.</returns> private static bool TryCoerceSpecialTypes(DynamicMetaObject thisOperand, DynamicMetaObject otherOperand, out Type coercedType) { JsonValue thisValue = thisOperand.Value as JsonValue; JsonValue otherValue = otherOperand.Value as JsonValue; if (thisValue is JsonPrimitive) { Type thisType = thisValue.Read().GetType(); if (thisType != otherOperand.LimitType) { if (otherOperand.LimitType == typeof(string) || (thisType == typeof(string) && otherValue == null)) { object value; if (thisValue.TryReadAs(otherOperand.LimitType, out value)) { coercedType = otherOperand.LimitType; return(true); } } } } coercedType = default(Type); return(false); }
/// <summary> /// Gets the operation support value for the specified operation on the specified operand. /// </summary> /// <param name="operation">The operation type.</param> /// <param name="thisValue">The JsonValue instance to check operation for.</param> /// <returns>An <see cref="OperationSupport"/> value.</returns> private static OperationSupport GetUnaryOperationSupport(ExpressionType operation, JsonValue thisValue) { //// Unary operators: +, -, !, ~, false (&&), true (||) //// unsupported: ++, -- switch (operation) { case ExpressionType.UnaryPlus: case ExpressionType.Negate: case ExpressionType.OnesComplement: case ExpressionType.IsFalse: case ExpressionType.IsTrue: break; case ExpressionType.Not: //// The DLR converts the 'Not' operation into a 'OnesComplement' operation for integer numbers, need to block that scenario. bool boolVal; if (!thisValue.TryReadAs <bool>(out boolVal)) { return(OperationSupport.NotSupportedOnOperand); } break; default: return(OperationSupport.NotSupported); } return(OperationSupport.Supported); }
/// <summary> /// Gets the return type for unary operations. /// </summary> /// <param name="binder">The unary operation binder.</param> /// <returns>The type representing the operation return type.</returns> private Type GetUnaryOperationReturnType(UnaryOperationBinder binder) { JsonValue thisValue = this.Value as JsonValue; Type returnType = binder.ReturnType == typeof(object) ? thisValue.Read().GetType() : binder.ReturnType; //// The DLR sets the binder.ReturnType for the unary 'Not' operation as 'object' as opposed to 'bool', //// we need to detect this case and fix up the type to enable boolean conversions from strings. if (returnType == typeof(string) && binder.Operation == ExpressionType.Not) { bool boolVal; if (thisValue.TryReadAs <bool>(out boolVal)) { returnType = typeof(bool); } } return(returnType); }
public void ReadAsTests() { JsonValue target = AnyInstance.DefaultJsonValue; string typeName = target.GetType().FullName; string errorMsgFormat = "Cannot read '{0}' as '{1}' type."; ExceptionHelper.Throws <NotSupportedException>(delegate { target.ReadAs(typeof(bool)); }, String.Format(errorMsgFormat, typeName, typeof(bool))); ExceptionHelper.Throws <NotSupportedException>(delegate { target.ReadAs(typeof(string)); }, String.Format(errorMsgFormat, typeName, typeof(string))); ExceptionHelper.Throws <NotSupportedException>(delegate { target.ReadAs(typeof(JsonObject)); }, String.Format(errorMsgFormat, typeName, typeof(JsonObject))); ExceptionHelper.Throws <NotSupportedException>(delegate { target.ReadAs <bool>(); }, String.Format(errorMsgFormat, typeName, typeof(bool))); ExceptionHelper.Throws <NotSupportedException>(delegate { target.ReadAs <string>(); }, String.Format(errorMsgFormat, typeName, typeof(string))); ExceptionHelper.Throws <NotSupportedException>(delegate { target.ReadAs <JsonObject>(); }, String.Format(errorMsgFormat, typeName, typeof(JsonObject))); bool boolValue; string stringValue; JsonObject objValue; object value; Assert.False(target.TryReadAs(typeof(bool), out value), "TryReadAs expected to return false"); Assert.Null(value); Assert.False(target.TryReadAs(typeof(string), out value), "TryReadAs expected to return false"); Assert.Null(value); Assert.False(target.TryReadAs(typeof(JsonObject), out value), "TryReadAs expected to return false"); Assert.Null(value); Assert.False(target.TryReadAs <bool>(out boolValue), "TryReadAs expected to return false"); Assert.False(boolValue); Assert.False(target.TryReadAs <string>(out stringValue), "TryReadAs expected to return false"); Assert.Null(stringValue); Assert.False(target.TryReadAs <JsonObject>(out objValue), "TryReadAs expected to return false"); Assert.Null(objValue); }