private static object CoerceProperty(object value, Type parameterType) { if (value == null) { return(null); } var valueType = value.GetType(); if (valueType.IsAssignmentCompatible(parameterType)) { if ((valueType.GetBoxedType() != parameterType.GetBoxedType()) && parameterType.IsNumeric() && valueType.IsNumeric()) { value = CoercerFactory.CoerceBoxed(value, parameterType.GetBoxedType()); } return(value); } return(value); }
public void TestGetCoercer() { Assert.AreEqual(1d, CoercerFactory.GetCoercer(null, typeof(double?)).Invoke(1d)); Assert.AreEqual(1d, CoercerFactory.GetCoercer(typeof(double?), typeof(double?)).Invoke(1d)); Assert.AreEqual(5d, CoercerFactory.GetCoercer(typeof(int?), typeof(double?)).Invoke(5)); Assert.AreEqual(6d, CoercerFactory.GetCoercer(typeof(byte?), typeof(double?)).Invoke((byte)6)); Assert.AreEqual(3f, CoercerFactory.GetCoercer(typeof(long?), typeof(float?)).Invoke((long)3)); Assert.AreEqual((short)2, CoercerFactory.GetCoercer(typeof(long?), typeof(short?)).Invoke((long)2)); Assert.AreEqual(4, CoercerFactory.GetCoercer(typeof(long?), typeof(int?)).Invoke((long)4)); Assert.AreEqual((byte)5, CoercerFactory.GetCoercer(typeof(long?), typeof(sbyte?)).Invoke((long)5)); Assert.AreEqual(8l, CoercerFactory.GetCoercer(typeof(long?), typeof(long?)).Invoke((long)8)); Assert.AreEqual(9.0m, CoercerFactory.GetCoercer(typeof(int), typeof(decimal)).Invoke(9)); Assert.AreEqual(9.0m, CoercerFactory.GetCoercer(typeof(double), typeof(decimal)).Invoke(9.0)); Assert.AreEqual(9.0m, CoercerFactory.GetCoercer(typeof(int), typeof(decimal?)).Invoke(9)); Assert.AreEqual(9.0m, CoercerFactory.GetCoercer(typeof(double), typeof(decimal?)).Invoke(9.0)); try { CoercerFactory.CoerceBoxed(10, typeof(char)); Assert.Fail(); } catch (ArgumentException) { // Expected } }
/// <summary>Returns the widener. </summary> /// <param name="columnName">name of column</param> /// <param name="columnType">type of column</param> /// <param name="writeablePropertyType">property type</param> /// <param name="writeablePropertyName">propery name</param> /// <returns>type widender</returns> /// <throws>ExprValidationException if type validation fails</throws> public static TypeWidener GetCheckPropertyAssignType(String columnName, Type columnType, Type writeablePropertyType, String writeablePropertyName) { Type columnClassBoxed = columnType.GetBoxedType(); Type targetClassBoxed = writeablePropertyType.GetBoxedType(); if (columnType == null) { if (writeablePropertyType.IsPrimitive) { String message = "Invalid assignment of column '" + columnName + "' of null type to event property '" + writeablePropertyName + "' typed as '" + writeablePropertyType.FullName + "', nullable type mismatch"; throw new ExprValidationException(message); } } else if (columnClassBoxed != targetClassBoxed) { if (columnClassBoxed == typeof(string) && targetClassBoxed == typeof(char?)) { return(TypeWidenerStringToCharCoercer.Widen); } if (columnClassBoxed.IsArray && targetClassBoxed.IsArray) { var columnClassElement = columnClassBoxed.GetElementType(); var targetClassElement = targetClassBoxed.GetElementType(); // By definition, columnClassElement and targetClassElement should be // incompatible. Question is, can we find a coercer between them? var coercer = CoercerFactory.GetCoercer(columnClassElement, targetClassElement); return(source => WidenArray(source, targetClassElement, coercer)); } if (!columnClassBoxed.IsAssignmentCompatible(targetClassBoxed)) { var writablePropName = writeablePropertyType.FullName; if (writeablePropertyType.IsArray) { writablePropName = writeablePropertyType.GetElementType().FullName + "[]"; } var columnTypeName = columnType.FullName; if (columnType.IsArray) { columnTypeName = columnType.GetElementType().FullName + "[]"; } String message = "Invalid assignment of column '" + columnName + "' of type '" + columnTypeName + "' to event property '" + writeablePropertyName + "' typed as '" + writablePropName + "', column and parameter types mismatch"; throw new ExprValidationException(message); } if (writeablePropertyType.IsNumeric()) { var instance = new TypeWidenerBoxedNumeric( CoercerFactory.GetCoercer(columnClassBoxed, targetClassBoxed)); return(instance.Widen); } } return(null); }
public static Object CoerceProperty(String propertyName, Type containingType, Object value, Type type, EngineImportService engineImportService, bool forceNumeric, bool includeClassNameInEx) { if (value is ExprNode && type != typeof(ExprNode)) { if (value is ExprIdentNode) { var identNode = (ExprIdentNode)value; Property prop; try { prop = PropertyParser.ParseAndWalk(identNode.FullUnresolvedName); } catch (Exception ex) { throw new ExprValidationException("Failed to parse property '" + identNode.FullUnresolvedName + "'"); } if (!(prop is MappedProperty)) { throw new ExprValidationException("Unrecognized property '" + identNode.FullUnresolvedName + "'"); } var mappedProperty = (MappedProperty)prop; if (mappedProperty.PropertyNameAtomic.ToLower() == ENVIRONMENT_PROPERTIES_NAME) { return(Environment.GetEnvironmentVariable(mappedProperty.Key)); } } else { var exprNode = (ExprNode)value; var evaluator = exprNode.ExprEvaluator; if (evaluator == null) { throw new ExprValidationException("Failed to evaluate expression '" + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(exprNode) + "'"); } value = evaluator.Evaluate(new EvaluateParams(null, true, null)); } } if (value == null) { return(null); } if (value.GetType() == type) { return(value); } if (value.GetType().IsAssignmentCompatible(type)) { if (forceNumeric && value.GetBoxedType() != type.GetBoxedType() && type.IsNumeric() && value.GetType().IsNumeric()) { value = CoercerFactory.CoerceBoxed(value, type.GetBoxedType()); } return(value); } if (TypeHelper.IsSubclassOrImplementsInterface(value.GetType(), type)) { return(value); } if (type.IsArray) { if (!(value.GetType().IsGenericCollection())) { string detail = "expects an array but receives a value of type " + value.GetType().FullName; throw new ExprValidationException(GetExceptionText(propertyName, containingType, includeClassNameInEx, detail)); } var items = value.UnwrapIntoArray <object>(); var coercedArray = Array.CreateInstance(type.GetElementType(), items.Length); for (var i = 0; i < items.Length; i++) { var coercedValue = CoerceProperty(propertyName + " (array element)", type, items[i], type.GetElementType(), engineImportService, false, includeClassNameInEx); coercedArray.SetValue(coercedValue, i); } return(coercedArray); } if (!(value is Map)) { string detail = "expects an " + TypeHelper.GetTypeNameFullyQualPretty(type) + " but receives a value of type " + value.GetType().FullName; throw new ExprValidationException(GetExceptionText(propertyName, containingType, includeClassNameInEx, detail)); } var props = (IDictionary <String, Object>)value; return(InstantiatePopulateObject(props, type, engineImportService)); }
/// <summary>Returns the widener. </summary> /// <param name="columnName">name of column</param> /// <param name="columnType">type of column</param> /// <param name="writeablePropertyType">property type</param> /// <param name="writeablePropertyName">propery name</param> /// <param name="allowObjectArrayToCollectionConversion">whether we widen object-array to collection</param> /// <param name="customizer">customization if any</param> /// <param name="engineURI">engine URI</param> /// <param name="statementName">statement name</param> /// <exception cref="ExprValidationException">if type validation fails</exception> /// <returns>type widender</returns> /// <throws>ExprValidationException if type validation fails</throws> public static TypeWidener GetCheckPropertyAssignType( String columnName, Type columnType, Type writeablePropertyType, String writeablePropertyName, bool allowObjectArrayToCollectionConversion, TypeWidenerCustomizer customizer, string statementName, string engineURI) { Type columnClassBoxed = TypeHelper.GetBoxedType(columnType); Type targetClassBoxed = TypeHelper.GetBoxedType(writeablePropertyType); if (customizer != null) { TypeWidener custom = customizer.WidenerFor(columnName, columnType, writeablePropertyType, writeablePropertyName, statementName, engineURI); if (custom != null) { return(custom); } } if (columnType == null) { if (writeablePropertyType.IsPrimitive) { String message = "Invalid assignment of column '" + columnName + "' of null type to event property '" + writeablePropertyName + "' typed as '" + writeablePropertyType.FullName + "', nullable type mismatch"; throw new ExprValidationException(message); } } else if (columnClassBoxed != targetClassBoxed) { if (columnClassBoxed == typeof(string) && targetClassBoxed == typeof(char?)) { return(TypeWidenerStringToCharCoercer.Widen); } if (allowObjectArrayToCollectionConversion && columnClassBoxed.IsArray && !columnClassBoxed.GetElementType().IsPrimitive && targetClassBoxed.IsGenericCollection()) { return(OBJECT_ARRAY_TO_COLLECTION_COERCER); } if (columnClassBoxed.IsGenericDictionary() && targetClassBoxed.IsGenericDictionary()) { var columnClassGenerics = columnClassBoxed.GetGenericArguments(); var targetClassGenerics = targetClassBoxed.GetGenericArguments(); var transformMethod = typeof(TransformDictionaryFactory) .GetMethod("Create", new[] { typeof(object) }) .MakeGenericMethod(targetClassGenerics[0], targetClassGenerics[1], columnClassGenerics[0], columnClassGenerics[1]); return(source => { var parameters = new object[] { source }; return transformMethod.Invoke(null, BindingFlags.Static | BindingFlags.Public, null, parameters, null); }); } if ((columnClassBoxed == typeof(string)) && (targetClassBoxed == typeof(char[]))) { return(source => { var sourceAsString = (string)source; return sourceAsString != null?sourceAsString.ToCharArray() : null; }); } if ((columnClassBoxed == typeof(char[])) && (targetClassBoxed == typeof(string))) { return(source => { var sourceAsCharArray = (char[])source; return sourceAsCharArray != null ? new string(sourceAsCharArray) : null; }); } if (columnClassBoxed.IsArray && targetClassBoxed.IsArray) { var columnClassElement = columnClassBoxed.GetElementType(); var targetClassElement = targetClassBoxed.GetElementType(); if (columnClassElement.IsAssignmentCompatible(targetClassElement)) { // By definition, columnClassElement and targetClassElement should be // incompatible. Question is, can we find a coercer between them? var coercer = CoercerFactory.GetCoercer(columnClassElement, targetClassElement); return(source => WidenArray(source, targetClassElement, coercer)); } } if (!columnClassBoxed.IsAssignmentCompatible(targetClassBoxed)) { var writablePropName = writeablePropertyType.FullName; if (writeablePropertyType.IsArray) { writablePropName = writeablePropertyType.GetElementType().FullName + "[]"; } var columnTypeName = columnType.FullName; if (columnType.IsArray) { columnTypeName = columnType.GetElementType().FullName + "[]"; } String message = "Invalid assignment of column '" + columnName + "' of type '" + columnTypeName + "' to event property '" + writeablePropertyName + "' typed as '" + writablePropName + "', column and parameter types mismatch"; throw new ExprValidationException(message); } if (writeablePropertyType.IsNumeric()) { var instance = new TypeWidenerBoxedNumeric( CoercerFactory.GetCoercer(columnClassBoxed, targetClassBoxed)); return(instance.Widen); } } return(null); }
public static Object CoerceProperty( string propertyName, Type containingType, Object value, Type type, ExprNodeOrigin exprNodeOrigin, ExprValidationContext exprValidationContext, bool forceNumeric, bool includeClassNameInEx) { if (value is ExprNode && type != typeof(ExprNode)) { if (value is ExprIdentNode) { var identNode = (ExprIdentNode)value; Property prop; try { prop = PropertyParser.ParseAndWalkLaxToSimple(identNode.FullUnresolvedName); } catch (Exception) { throw new ExprValidationException( "Failed to parse property '" + identNode.FullUnresolvedName + "'"); } if (!(prop is MappedProperty)) { throw new ExprValidationException( "Unrecognized property '" + identNode.FullUnresolvedName + "'"); } var mappedProperty = (MappedProperty)prop; if (string.Equals( mappedProperty.PropertyNameAtomic, SYSTEM_PROPETIES_NAME, StringComparison.InvariantCultureIgnoreCase)) { return(Environment.GetEnvironmentVariable(mappedProperty.Key)); } } else { var exprNode = (ExprNode)value; var validated = ExprNodeUtility.GetValidatedSubtree( exprNodeOrigin, exprNode, exprValidationContext); exprValidationContext.VariableService.SetLocalVersion(); var evaluator = validated.ExprEvaluator; if (evaluator == null) { throw new ExprValidationException( "Failed to evaluate expression '" + ExprNodeUtility.ToExpressionStringMinPrecedenceSafe(exprNode) + "'"); } value = evaluator.Evaluate(EvaluateParams.EmptyTrue); } } if (value == null) { return(null); } var valueType = value.GetType(); if (valueType == type) { return(value); } if (valueType.IsAssignmentCompatible(type)) { if (forceNumeric && (valueType.GetBoxedType() != type.GetBoxedType()) && type.IsNumeric() && valueType.IsNumeric()) { value = CoercerFactory.CoerceBoxed(value, type.GetBoxedType()); } return(value); } #if false // numerical coercion between non-boxed types and incompatible boxed types if ((valueType.IsNumeric()) && (valueType.IsNullable() == false) && (type.IsNumeric()) && (type.IsNullable())) { var typeNonGeneric = Nullable.GetUnderlyingType(type); if (valueType.IsAssignmentCompatible(typeNonGeneric)) { value = CoercerFactory.CoerceBoxed(value, type); } return(value); } #endif if (TypeHelper.IsSubclassOrImplementsInterface(valueType, type)) { return(value); } if (type.IsArray) { if (!(valueType.IsGenericCollection())) { var detail = "expects an array but receives a value of type " + valueType.GetCleanName(); throw new ExprValidationException( GetExceptionText(propertyName, containingType, includeClassNameInEx, detail)); } var items = value.UnwrapIntoArray <object>(); var coercedArray = Array.CreateInstance(type.GetElementType(), items.Length); for (var i = 0; i < items.Length; i++) { var coercedValue = CoerceProperty( propertyName + " (array element)", type, items[i], type.GetElementType(), exprNodeOrigin, exprValidationContext, false, includeClassNameInEx); coercedArray.SetValue(coercedValue, i); } return(coercedArray); } if (type.IsNullable() && !valueType.IsNullable()) { var typeNonGeneric = Nullable.GetUnderlyingType(type); if (valueType.IsAssignmentCompatible(typeNonGeneric)) { return(CoercerFactory.CoerceBoxed(value, type)); } } if (!(value is IDictionary <String, Object>)) { var detail = "expects an " + type.GetCleanName() + " but receives a value of type " + valueType.GetCleanName(); throw new ExprValidationException( GetExceptionText(propertyName, containingType, includeClassNameInEx, detail)); } var props = (IDictionary <string, Object>)value; return(InstantiatePopulateObject(props, type, exprNodeOrigin, exprValidationContext)); }