internal static IDictionary <string, object?> ToDictionaryInternal(this object instance, ConverterSettings settings) { var instanceType = instance.GetType(); if (settings.TryGetMatchingConverter(instanceType, out MemberConverter? converter)) { return((IDictionary <string, object?>)converter.Convert(instance, settings)); } var resolver = settings.ResolverInternal; var members = resolver.GetMemberInfos(instanceType); var resultDictionary = new Dictionary <string, object?>(members.Length); foreach (var member in members) { var key = member.GetName(resolver); var value = member.GetValue(instance, resolver); if (value == null || value.GetType().IsSimpleType()) { resultDictionary[key] = value; continue; } if (settings.TryGetMatchingConverter(value.GetType(), out converter)) { resultDictionary[key] = converter.Convert(value, settings); continue; } resultDictionary[key] = value.ToDictionaryInternal(settings); } return(resultDictionary); }
internal static object ToInstanceInternal(this Dictionary <string, object?> dictionary, Type type, ConverterSettings settings) { if (settings.TryGetMatchingConverter(type, out MemberConverter? converter)) { return(converter.ConvertBack(dictionary, type, settings) ?? throw new InvalidOperationException($"Cannot convert {dictionary.GetType().Name} to {type.Name}")); } var instance = Activator.CreateInstance(type); var resolver = settings.ResolverInternal; var members = resolver.GetMemberInfos(type); foreach (var element in dictionary) { var member = members.FindMatch(element.Key, resolver); if (member == null) { // Think about a 'AllKeysMustMatch' solution continue; } var value = element.Value; var memberType = member.GetMemberType(); if (value != null) { // Try to convert non nullable values if (value.TryConvertValue(memberType, settings, out object?conValue)) { member.SetValue(instance, conValue); continue; } // Try to use matching converter if (settings.TryGetMatchingConverter(memberType, out converter)) { member.SetValue(instance, converter.ConvertBack(value, memberType, settings)); continue; } } // Assign null if member type allows null assignment else if (!memberType.IsValueType || memberType.TryGetNonNullableType(out Type _)) { member.SetValue(instance, null); continue; } // Try to convert generic member if (TryConvertGenericValue(value, memberType, settings, out object?genValue)) { member.SetValue(instance, genValue); continue; } // Recursive call if value is a dictionary if (value is IDictionary dict2) { member.SetValue(instance, ((Dictionary <string, object?>)dict2).ToInstanceInternal(memberType, settings)); continue; } throw new NotSupportedException($"'{value?.ToString()}' cannot be assigned to '{member.Name}' or cannot converted to '{memberType.Name}'"); } return(instance); }