public static bool TryConvert <T>(object value, out T result) { // Check for null if (value == null) { result = default(T); return(!typeof(T).IsValueType); } // Just return if they're the same type if (typeof(T) == value.GetType()) { result = (T)value; return(true); } // Check a normal conversion (in case it's a special type that implements a cast, IConvertible, or something) if (MetadataTypeConverter <T> .TryConvert(value, out result)) { return(true); } // Check for enumerable conversions (but don't treat string as an enumerable) IEnumerable enumerable = value is string?null : value as IEnumerable; enumerable = enumerable ?? new[] { value }; // IList<> if (typeof(T).IsConstructedGenericType && typeof(T).GetGenericTypeDefinition() == typeof(IList <>)) { Type elementType = typeof(T).GetGenericArguments()[0]; Type adapterType = typeof(MetadataTypeConverter <>).MakeGenericType(elementType); MetadataTypeConverter converter = (MetadataTypeConverter)Activator.CreateInstance(adapterType); result = (T)converter.ToList(enumerable); return(true); } // Array if (typeof(T).IsArray && typeof(T).GetArrayRank() == 1) { Type elementType = typeof(T).GetElementType(); Type adapterType = typeof(MetadataTypeConverter <>).MakeGenericType(elementType); MetadataTypeConverter converter = (MetadataTypeConverter)Activator.CreateInstance(adapterType); result = (T)converter.ToArray(enumerable); return(true); } // IEnumerable<> if (typeof(T).IsConstructedGenericType && typeof(T).GetGenericTypeDefinition() == typeof(IEnumerable <>)) { Type elementType = typeof(T).GetGenericArguments()[0]; Type adapterType = typeof(MetadataTypeConverter <>).MakeGenericType(elementType); MetadataTypeConverter converter = (MetadataTypeConverter)Activator.CreateInstance(adapterType); result = (T)converter.ToEnumerable(enumerable); return(true); } return(false); }
public static bool TryConvert <T>(object value, out T result) { // Check for null if (value == null) { result = default(T); return(!typeof(T).IsValueType); } // Just return if they're the same type if (typeof(T) == value.GetType()) { result = (T)value; return(true); } // Check a normal conversion (in case it's a special type that implements a cast, IConvertible, or something) if (MetadataTypeConverter <T> .TryConvert(value, out result)) { return(true); } // IReadOnlyList<> if (typeof(T).IsConstructedGenericType && typeof(T).GetGenericTypeDefinition() == typeof(IReadOnlyList <>)) { return(TryConvertEnumerable(value, x => x.GetGenericArguments()[0], (x, y) => x.ToReadOnlyList(y), out result)); } // IList<> if (typeof(T).IsConstructedGenericType && (typeof(T).GetGenericTypeDefinition() == typeof(IList <>) || typeof(T).GetGenericTypeDefinition() == typeof(List <>))) { return(TryConvertEnumerable(value, x => x.GetGenericArguments()[0], (x, y) => x.ToList(y), out result)); } // Array if (typeof(Array).IsAssignableFrom(typeof(T)) || (typeof(T).IsArray && typeof(T).GetArrayRank() == 1)) { return(TryConvertEnumerable(value, x => x.GetElementType() ?? typeof(object), (x, y) => x.ToArray(y), out result)); } // IEnumerable<> if (typeof(T).IsConstructedGenericType && typeof(T).GetGenericTypeDefinition() == typeof(IEnumerable <>)) { return(TryConvertEnumerable(value, x => x.GetGenericArguments()[0], (x, y) => x.ToEnumerable(y), out result)); } return(false); }
private static bool TryConvertEnumerable <T>(object value, Func <Type, Type> elementTypeFunc, Func <MetadataTypeConverter, IEnumerable, object> conversionFunc, out T result) { Type elementType = elementTypeFunc(typeof(T)); IEnumerable enumerable = value is string?null : value as IEnumerable; if (enumerable == null || elementType.IsInstanceOfType(value)) { enumerable = new[] { value }; } Type adapterType = typeof(MetadataTypeConverter <>).MakeGenericType(elementType); MetadataTypeConverter converter = (MetadataTypeConverter)Activator.CreateInstance(adapterType); result = (T)conversionFunc(converter, enumerable); return(true); }