コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }