public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { var instance = MethodFactory.CreateInstance(destinationType); var classDescription = serializationContext.GetClassDescription(destinationType, instance); var source = value as IDictionary <string, object>; if (source != null) { foreach (var kv in source) { IMemberWrapper wrapper; if (classDescription.TryGetMember(kv.Key, out wrapper)) { wrapper.SetValue(instance, kv.Value); } } return(instance); } return(base.ConvertTo(context, culture, value, destinationType)); }
// Add the type to the list of creatable types public void Register(Type type) { if (type.IsEnum || constructors.ContainsKey(type)) { return; } var constructor = type.GetConstructors().FirstOrDefault(x => x.GetParameters().Length == 0); if (constructor == null) { throw new ArgumentException($"{type.FullName} does not have any accessible parameterless constructors.", nameof(type)); } constructors[type] = MethodFactory.CompileObjectConstructor(constructor); var attributes = type.GetCustomAttributes <SerializedNameAttribute>(false).ToArray(); if (attributes.Length == 0) { remoteToLocalNames[type.FullName] = type; } else if (attributes.Count(x => x.Canonical) == 1) { foreach (var attribute in attributes) { RegisterAlias(type, attribute.SerializedName, attribute.Canonical); } } else { throw new ArgumentException( $"{type.FullName} has {attributes.Count(x => x.Canonical)} candidate names marked as canonical. only one can be canonical.", nameof(type)); } }
public static object ConvertTo(object value, Type targetType) { if (value == null) { return(CreateDefaultValue(targetType)); } var sourceType = value.GetType(); if (sourceType == targetType || targetType.IsInstanceOfType(value)) { return(value); } // IConvertible if (sourceType.IsConvertible() && targetType.IsConvertible()) { if (targetType.IsEnum) { var stringValue = value as string; return(stringValue != null ? Enum.Parse(targetType, stringValue, true) : Enum.ToObject(targetType, value)); } return(ConvertObject(sourceType, targetType, value)); } var ienumerable = value as IEnumerable; // array if (targetType.IsArray && ienumerable != null) { var sourceElementType = sourceType.GetElementType(); var destinationElementType = targetType.GetElementType(); var enumerable = ienumerable.Cast <object>(); if (!destinationElementType.IsAssignableFrom(sourceElementType)) { enumerable = enumerable.Select(x => ConvertTo(x, destinationElementType)); } var method = EnumerableToArrayCache.GetOrAdd(destinationElementType, type => EnumerableToArrayMethod.MakeGenericMethod(type)); return(method.Invoke(null, new object[] { enumerable })); } // IDictionary<K, V> // - we always deserialize AMF dictionaries as Dictionary<string, object> (or an object that inherits from it) var sourceGenericDictionary = value as IDictionary <string, object>; var genericDictionaryType = TryGetInterfaceType(targetType, typeof(IDictionary <,>)); if (sourceGenericDictionary != null && genericDictionaryType != null) { var instance = MethodFactory.CreateInstance(targetType); var adder = AdderMethodCache.GetOrAdd(genericDictionaryType, type => new AdderMethodInfo(type)); foreach (var pair in sourceGenericDictionary) { adder.Method.Invoke(instance, new[] { ConvertTo(pair.Key, adder.TypeGenericParameters[0]), ConvertTo(pair.Value, adder.TypeGenericParameters[1]) }); } return(instance); } // IDictionary var souceDictionary = value as IDictionary; if (typeof(IDictionary).IsAssignableFrom(targetType) && souceDictionary != null) { var instance = (IDictionary)MethodFactory.CreateInstance(targetType); foreach (DictionaryEntry pair in souceDictionary) { instance.Add(pair.Key, pair.Value); } return(instance); } // IList<T> var sourceListType = TryGetInterfaceType(targetType, typeof(IList <>)); if (sourceListType != null && ienumerable != null) { var instance = MethodFactory.CreateInstance(targetType); var adder = AdderMethodCache.GetOrAdd(sourceListType, type => new AdderMethodInfo(type)); foreach (var item in ienumerable) { adder.Method.Invoke(instance, new object[] { ConvertTo(item, adder.TypeGenericParameters[0]) }); } return(instance); } // IList if (typeof(IList).IsAssignableFrom(targetType) && ienumerable != null) { var instance = (IList)MethodFactory.CreateInstance(targetType); foreach (var item in ienumerable) { instance.Add(item); } return(instance); } // Guid if (targetType == typeof(Guid)) { var input = value as string; if (input != null) { return(Guid.Parse(input)); } var bytes = value as byte[]; if (bytes != null) { return(new Guid(bytes)); } } // Nullable<T> if (targetType.IsNullable()) { var underlyingType = Nullable.GetUnderlyingType(targetType); return(Convert.ChangeType(value, underlyingType, CultureInfo.InvariantCulture)); } return(ConvertObject(sourceType, targetType, value)); }