Пример #1
0
        public static bool Convert(object val, Type targetType, out object result)
        {
            result = val;
            // Trivial cases
            if (val == null)
            {
                // Cannot convert null to value type
                return(!targetType.IsValueType);
            }
            if (targetType.IsAssignableFrom(val.GetType()))
            {
                return(true);
            }

            // Custom type conversions

            if (_customTypeConverter != null)
            {
                if (_customTypeConverter(val, targetType, out result))
                {
                    return(true);
                }
            }

            // TODO: typeof(Nullable<T>)

            // Built-in type conversions

            if (val.GetType() == typeof(string) && targetType == typeof(Type))
            { // string -> Type
                result = Type.GetType(val.ToString());
                return(result != null);
            }

            // Enumerations
            if (val.GetType() == typeof(string) && targetType.IsEnum)
            { // string -> Enum
                result = Enum.Parse(targetType, (string)val);
                return(true);
            }

            // String target type must be done before enumerations are tried - else, the string will be treated as enumeration
            if (targetType.IsAssignableFrom(typeof(string)))
            { // * -> string
                result = val.ToString();
                return(true);
            }

            // Collection types

            Type enumerableType;
            Type entryType;

            ReflectionHelper.FindImplementedEnumerableType(targetType, out enumerableType, out entryType);

            if (enumerableType != null) // Targets IList, ICollection, IList<>, ICollection<>
            {
                ICollection col;
                if (!ToCollection(val, entryType, out col))
                {
                    return(false);
                }
                List <object> resultList = col.Cast <object>().ToList();
                result = resultList;
                return(true);
            }
            ICollection sourceCol = val as ICollection;

            if (sourceCol != null && sourceCol.Count == 1) // From collection to non-collection target
            {
                // Use the first (single) item of a collection or dictionary
                IEnumerator enumerator = sourceCol.GetEnumerator();
                enumerator.MoveNext();
                object item = enumerator.Current;
                if (Convert(item, targetType, out result)) // Single collection item
                {
                    return(true);
                }
                KeyValuePair <object, object>?kvp = item as KeyValuePair <object, object>?;
                if (kvp.HasValue && Convert(kvp.Value.Value, targetType, out result)) // Value of single dictionary entry - generic dictionary
                {
                    IDisposable d = kvp.Value.Key as IDisposable;
                    if (d != null)
                    {
                        d.Dispose();
                    }
                    return(true);
                }
                DictionaryEntry?entry = item as DictionaryEntry?;
                if (entry.HasValue && Convert(entry.Value.Value, targetType, out result)) // Value of single dictionary entry - legacy dictionary
                {
                    IDisposable d = entry.Value.Key as IDisposable;
                    if (d != null)
                    {
                        d.Dispose();
                    }
                    return(true);
                }
            }

            // Simple type conversions

            System.ComponentModel.TypeConverter tc = TypeDescriptor.GetConverter(targetType);
            if (tc != null && tc.CanConvertFrom(val.GetType()))
            {
                try
                {
                    result = tc.ConvertFrom(null, CultureInfo.InvariantCulture, val);
                    return(true);
                }
                catch { }
            }

            tc = TypeDescriptor.GetConverter(val);
            if (tc != null && tc.CanConvertTo(targetType))
            {
                result = tc.ConvertTo(val, targetType);
                return(true);
            }

            return(false);
        }