예제 #1
0
        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);
        }
예제 #2
0
        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
            }
        }
예제 #3
0
        /// <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);
        }
예제 #4
0
        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));
        }
예제 #5
0
        /// <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);
        }
예제 #6
0
        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));
        }