예제 #1
0
        public void CoerceType_DictionaryToExpando_CoercesViaDictionaryCopy()
        {
            var input = new Hashtable
            {
                { "One", 1 },
                { "Two", 2 },
                { "Three", 3 },
                { "Four", 4 }
            };

            dynamic expected = new ExpandoObject();

            expected.One   = 1;
            expected.Two   = 2;
            expected.Three = 3;
            expected.Four  = 4;

            var settings = new DataReaderSettings();
            var actual   = new TypeCoercionUtility(settings, settings.AllowNullValueTypes).CoerceType(expected.GetType(), input);

            Assert.Equal(expected, actual);
        }
예제 #2
0
        public void CoerceType_ExpandoToGenericDictionary_CoercesViaGenericDictionaryCopy()
        {
            dynamic input = new ExpandoObject();

            input.One   = 1;
            input.Two   = 2;
            input.Three = 3;
            input.Four  = 4;

            var expected = new Dictionary <string, object>
            {
                { "One", 1 },
                { "Two", 2 },
                { "Three", 3 },
                { "Four", 4 }
            };

            var settings = new DataReaderSettings();
            var actual   = new TypeCoercionUtility(settings, settings.AllowNullValueTypes).CoerceType(typeof(Dictionary <string, object>), input);

            Assert.Equal(expected, actual);
        }
예제 #3
0
        public void CoerceType_ListToArray_CoercesViaListCtor()
        {
            var input = new List <string>
            {
                "One",
                "Two",
                "Three",
                "Four"
            };

            var expected = new string[]
            {
                "One",
                "Two",
                "Three",
                "Four"
            };

            var settings = new DataReaderSettings();
            var actual   = new TypeCoercionUtility(settings, settings.AllowNullValueTypes).CoerceType(expected.GetType(), input);

            Assert.Equal(expected, actual);
        }
예제 #4
0
        private object CoerceList(Type targetType, Type valueType, IEnumerable value)
        {
            targetType = TypeCoercionUtility.ResolveInterfaceType(targetType);

            if (targetType.IsArray)
            {
                // arrays are much simpler to create
                return(this.CoerceArray(targetType.GetElementType(), value));
            }

            // targetType serializes as a JSON array but is not an array
            // assume is an ICollection or IEnumerable with AddRange, Add,
            // or custom Constructor with which we can populate it

            FactoryMap factory = this.ResolverCache.LoadFactory(targetType);

            if (factory == null)
            {
                throw new TypeCoercionException(String.Format(
                                                    TypeCoercionUtility.ErrorCtor,
                                                    targetType.FullName));
            }

            foreach (Type argType in factory.ArgTypes)
            {
                if (argType.IsAssignableFrom(valueType))
                {
                    try
                    {
                        // invoke first constructor that can take this value as an argument
                        return(factory[argType](value));
                    }
                    catch
                    {
                        // there might exist a better match
                        continue;
                    }
                }
            }

            if (factory.Ctor == null)
            {
                throw new TypeCoercionException(String.Format(
                                                    TypeCoercionUtility.ErrorCtor,
                                                    targetType.FullName));
            }

            // attempt bulk insert first as is most efficient
            if (factory.AddRange != null &&
                factory.AddRangeType != null &&
                factory.AddRangeType.IsAssignableFrom(valueType))
            {
                object collection = factory.Ctor();
                factory.AddRange(collection, value);
                return(collection);
            }

            // attempt sequence of single inserts next
            if (factory.Add != null &&
                factory.AddType != null)
            {
                object collection = factory.Ctor();
                Type   addType    = factory.AddType;

                // loop through adding items to collection
                foreach (object item in value)
                {
                    factory.Add(collection, this.CoerceType(addType, item));
                }
                return(collection);
            }

            try
            {
                // finally fall back to basics
                return(Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture));
            }
            catch (Exception ex)
            {
                throw new TypeCoercionException(
                          String.Format(
                              "Error converting {0} to {1}",
                              value.GetType().FullName,
                              targetType.FullName),
                          ex);
            }
        }
예제 #5
0
        /// <summary>
        /// Coerces the object value to Type of <paramref name="targetType"/>
        /// </summary>
        /// <param name="targetType"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public object CoerceType(Type targetType, object value)
        {
            if (targetType == null || targetType == typeof(object))
            {
                return(value);
            }

            bool isNullable = TypeCoercionUtility.IsNullable(targetType);

            if (value == null)
            {
                // TODO: validate that this is what we want

                if (!this.AllowNullValueTypes &&
                    targetType.IsValueType &&
                    !isNullable)
                {
                    throw new TypeCoercionException(String.Format(
                                                        TypeCoercionUtility.ErrorNullValueType,
                                                        targetType.FullName));
                }
                return(value);
            }

            if (isNullable)
            {
                // nullable types have a real underlying struct
                Type[] genericArgs = targetType.GetGenericArguments();
                if (genericArgs.Length == 1)
                {
                    targetType = genericArgs[0];
                }
            }

            Type actualType = value.GetType();

            if (targetType.IsAssignableFrom(actualType))
            {
                return(value);
            }

            if (targetType.IsEnum)
            {
                if (value is String)
                {
                    if (!Enum.IsDefined(targetType, value))
                    {
                        IDictionary <string, MemberMap> maps = this.ResolverCache.LoadMaps(targetType);
                        if (maps != null && maps.ContainsKey((string)value))
                        {
                            value = maps[(string)value].Name;
                        }
                    }

                    return(Enum.Parse(targetType, (string)value, false));
                }
                else
                {
                    value = this.CoerceType(Enum.GetUnderlyingType(targetType), value);
                    return(Enum.ToObject(targetType, value));
                }
            }

            if (value is IDictionary <string, object> )
            {
                return(this.CoerceType(targetType, (IDictionary <string, object>)value));
            }
            else if (value is IDictionary)
            {
                return(this.CoerceType(targetType, (IDictionary)value));
            }

            if (typeof(IEnumerable).IsAssignableFrom(targetType) &&
                typeof(IEnumerable).IsAssignableFrom(actualType))
            {
                return(this.CoerceList(targetType, actualType, (IEnumerable)value));
            }

            if (value is String)
            {
                if (targetType == typeof(DateTime))
                {
                    DateTime date;
                    try{
                        date = DateTime.Parse(
                            (string)value,
                            CultureInfo.InvariantCulture,
                            DateTimeStyles.RoundtripKind | DateTimeStyles.AllowWhiteSpaces | DateTimeStyles.NoCurrentDateDefault);
                        if (date.Kind == DateTimeKind.Local)
                        {
                            return(date.ToUniversalTime());
                        }
                        return(date);
                    }catch (Exception) {}

                    if (JsonFx.Model.Filters.MSAjaxDateFilter.TryParseMSAjaxDate(
                            (string)value,
                            out date))
                    {
                        return(date);
                    }
                }
                else if (targetType == typeof(Guid))
                {
                    // try-catch is pointless since will throw upon generic conversion
                    return(new Guid((string)value));
                }
                else if (targetType == typeof(Char))
                {
                    if (((string)value).Length == 1)
                    {
                        return(((string)value)[0]);
                    }
                }
                else if (targetType == typeof(Uri))
                {
                    Uri uri;
                    if (Uri.TryCreate((string)value, UriKind.RelativeOrAbsolute, out uri))
                    {
                        return(uri);
                    }
                }
                else if (targetType == typeof(Version))
                {
                    // try-catch is pointless since will throw upon generic conversion
                    return(new Version((string)value));
                }
                else if (targetType == typeof(TimeSpan))
                {
                    try{
                        return(TimeSpan.FromTicks(Int64.Parse((string)value)));
                    }catch (Exception) {}
                    try{
                        return(TimeSpan.Parse((string)value));
                    }catch (Exception) {}
                }
            }
            else if (targetType == typeof(TimeSpan))
            {
                return(new TimeSpan((long)this.CoerceType(typeof(Int64), value)));
            }

#if !SILVERLIGHT
            TypeConverter converter = TypeDescriptor.GetConverter(targetType);
            if (converter.CanConvertFrom(actualType))
            {
                return(converter.ConvertFrom(value));
            }

            converter = TypeDescriptor.GetConverter(actualType);
            if (converter.CanConvertTo(targetType))
            {
                return(converter.ConvertTo(value, targetType));
            }
#endif

            try
            {
                // fall back to basics
                return(Convert.ChangeType(value, targetType, CultureInfo.InvariantCulture));
            }
            catch (Exception ex)
            {
                throw new TypeCoercionException(
                          String.Format(
                              "Error converting {0} to {1}",
                              value.GetType().FullName,
                              targetType.FullName),
                          ex);
            }
        }
예제 #6
0
        /// <summary>
        /// Instantiates a new instance of objectType.
        /// </summary>
        /// <param name="objectType"></param>
        /// <returns>objectType instance</returns>
        internal object InstantiateObject(Type targetType, object args)
        {
            targetType = TypeCoercionUtility.ResolveInterfaceType(targetType);

            FactoryMap factory = this.ResolverCache.LoadFactory(targetType);

            if ((factory == null) || (factory.Ctor == null))
            {
                throw new TypeCoercionException(String.Format(
                                                    TypeCoercionUtility.ErrorCtor,
                                                    targetType.FullName));
            }

            if ((factory.CtorArgs == null) || (factory.CtorArgs.Length < 1))
            {
                // default constructor
                return(factory.Ctor());
            }

            object[] ctorArgs = new object[factory.CtorArgs.Length];

            IDictionary <string, object> genericArgs = args as IDictionary <string, object>;

            if (genericArgs != null)
            {
                for (int i = 0, length = ctorArgs.Length; i < length; i++)
                {
                    string name = factory.CtorArgs[i].Name;
                    Type   type = factory.CtorArgs[i].ParameterType;

                    foreach (string key in genericArgs.Keys)
                    {
                        try
                        {
                            if (StringComparer.OrdinalIgnoreCase.Equals(key, name))
                            {
                                ctorArgs[i] = this.CoerceType(type, genericArgs[key]);
                                break;
                            }
                        }
                        catch { }
                    }
                }
            }
            else
            {
                IDictionary otherArgs = args as IDictionary;
                if (otherArgs != null)
                {
                    for (int i = 0, length = ctorArgs.Length; i < length; i++)
                    {
                        string name = factory.CtorArgs[i].Name;
                        Type   type = factory.CtorArgs[i].ParameterType;

                        foreach (string key in otherArgs.Keys)
                        {
                            try
                            {
                                if (StringComparer.OrdinalIgnoreCase.Equals(key, name))
                                {
                                    ctorArgs[i] = this.CoerceType(type, otherArgs[key]);
                                    break;
                                }
                            }
                            catch { }
                        }
                    }
                }
            }

            // use a custom constructor
            return(factory.Ctor(ctorArgs));
        }