示例#1
0
        private static Func <DeserializationContext, object> ForCollection(Type type, Func <Type, TypeDescriptor> descriptorSource)
        {
            var element           = ReflectionUtils.FindCollectionElementType(type);
            var constructor       = ReflectionUtils.BuildConstructor(typeof(List <>).MakeGenericType(element));
            var elementDescriptor = descriptorSource(element);

            return(context =>
            {
                var reader = context.Reader;
                var bufferPart = new BufferPart();
                var token = reader.Read(ref bufferPart, out var _);
                if (token == JsonToken.Null)
                {
                    return null;
                }
                var target = (IList)constructor();
                if (token != JsonToken.ArrayStart)
                {
                    throw Exceptions.BadToken(reader, token, JsonToken.ObjectStart);
                }

                var finalizer = type.IsArray
                                        ? new Func <IList, object>(i =>
                {
                    var array = Array.CreateInstance(element, i.Count);
                    i.CopyTo(array, 0);
                    return array;
                })
                                        : null;

                var isFirst = true;
                while (true)
                {
                    if (reader.PeekToken() == JsonToken.ArrayEnd)
                    {
                        reader.Read(ref bufferPart, out var _);
                        return finalizer != null?finalizer(target) : target;
                    }
                    if (!isFirst)
                    {
                        token = reader.Read(ref bufferPart, out var _);
                        if (token != JsonToken.ValueSeparator)
                        {
                            throw Exceptions.BadToken(reader, token, JsonToken.ValueSeparator);
                        }
                    }

                    var item = elementDescriptor.Reader(context);
                    target.Add(item);

                    isFirst = false;
                }
            });
        }
示例#2
0
        private static Func <DeserializationContext, object> ForComplex(Type type, TypeOptions options, Func <Type, TypeDescriptor> descriptorSource)
        {
            var info = type.GetTypeInfo();

            if (info.IsClass && info.GetConstructor(Type.EmptyTypes) == null)
            {
                return(reader => throw new JsonException(info.IsAbstract
                                        ? $"Type {type} is abstract. Add {nameof(ITypeSelector)} to {nameof(SerializationSettings)} in order to deserialize this type."
                                        : $"Type {type} must define public parameterless constructor."));
            }

            var properties = info
                             .GetProperties(BindingFlags.Instance | BindingFlags.Public)
                             .Where(i => i.SetMethod != null && i.GetMethod != null)
                             .Select(i => new { Property = (MemberInfo)i, Setter = ReflectionUtils.BuildSetter(i), Descriptor = descriptorSource(i.PropertyType) });

            var fields = info
                         .GetFields(BindingFlags.Instance | BindingFlags.Public)
                         .Select(i => new { Property = (MemberInfo)i, Setter = ReflectionUtils.BuildFieldSetter(i), Descriptor = descriptorSource(i.FieldType) });

            var all = properties
                      .Concat(fields)
                      .SelectMany(i => JsonNames(i.Property).Select(j => new PropertyBinding {
                Name = j, Setter = i.Setter, Descriptor = i.Descriptor
            }))
                      .GroupBy(i => i.Name)
                      .ToDictionary(i => i.Key, i => i.First());

            var constructor = info.IsClass
                                ? ReflectionUtils.BuildConstructor(type)
                                : () => Activator.CreateInstance(typeof(Box <>).MakeGenericType(type));

            //struct types are internally wrapped into Box<T> type (see ReflectionUtils)
            var unwrapper = !info.IsClass
                                ? new Func <object, object>(i => ((IBox)i).Value)
                                : null;

            return(context =>
            {
                var bufferPart = new BufferPart();
                var reader = context.Reader;
                var token = reader.Read(ref bufferPart, out var _);
                if (token == JsonToken.Null)
                {
                    return info.IsClass ? (object)null : throw new JsonException($"Unable to assign null value to struct type near line {reader.Line}, column {reader.Column}.");
                }
                if (token != JsonToken.ObjectStart)
                {
                    throw Exceptions.BadToken(reader, token, JsonToken.ObjectStart);
                }
                var target = constructor();
                var deferred = ReadProperties(target, context, all);
                var unwrapped = unwrapper != null?unwrapper(target) : target;

                if (deferred == null)
                {
                    return unwrapped;
                }

                foreach (var entry in deferred)
                {
                    var runtimeType = entry.Selector.FindPropertyType(entry.Binding.Name, unwrapped);
                    var descriptor = context.Catalog.GetDescriptor(runtimeType, options);
                    using (reader.LoadSnapshot(entry.Snapshot))
                        entry.Binding.Setter(target, descriptor.Reader(context));
                }
                return unwrapper != null?unwrapper(target) : target;
            });
        }