Пример #1
0
        public override ValueSerializer BuildSerializer(Serializer serializer, Type type,
                                                        ConcurrentDictionary <Type, ValueSerializer> typeMapping)
        {
            var os = new ObjectSerializer(type);

            if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index))
            {
                var wrapper = new KnownTypeObjectSerializer(os, index);
                typeMapping.TryAdd(type, wrapper);
            }
            else
            {
                typeMapping.TryAdd(type, os);
            }
            var          methodInfoSerializer     = serializer.GetSerializerByType(typeof(MethodInfo));
            var          preserveObjectReferences = serializer.Options.PreserveObjectReferences;
            ObjectReader reader = (stream, session) =>
            {
                var target = stream.ReadObject(session);
                var method = (MethodInfo)stream.ReadObject(session);
                var del    = method.CreateDelegate(type, target);
                return(del);
            };
            ObjectWriter writer = (stream, value, session) =>
            {
                var d      = (Delegate)value;
                var method = d.GetMethodInfo();
                stream.WriteObjectWithManifest(d.Target, session);
                //less lookups, slightly faster
                stream.WriteObject(method, type, methodInfoSerializer, preserveObjectReferences, session);
            };

            os.Initialize(reader, writer);
            return(os);
        }
Пример #2
0
        public override ValueSerializer BuildSerializer(Serializer serializer, Type type,
                                                        ConcurrentDictionary <Type, ValueSerializer> typeMapping)
        {
            var exceptionSerializer   = new ObjectSerializer(type);
            var hasDefaultConstructor = type.GetTypeInfo().GetConstructor(new Type[0]) != null;
            var createInstance        = hasDefaultConstructor ? Activator.CreateInstance : GetUninitializedObject;

            exceptionSerializer.Initialize((stream, session) =>
            {
                var exception = createInstance(type);
                var className = stream.ReadString(session);
                var message   = stream.ReadString(session);
                var remoteStackTraceString = stream.ReadString(session);
                var stackTraceString       = stream.ReadString(session);
                var innerException         = stream.ReadObject(session);

#if NETSTANDARD20
                _className?.SetValue(exception, className);
#else
                _className.SetValue(exception, className);
#endif
                _message.SetValue(exception, message);
                _remoteStackTraceString.SetValue(exception, remoteStackTraceString);
                _stackTraceString.SetValue(exception, stackTraceString);
                _innerException.SetValue(exception, innerException);
                return(exception);
            }, (stream, exception, session) =>
            {
#if NETSTANDARD20
                var className = (string)_className?.GetValue(exception);
#else
                var className = (string)_className.GetValue(exception);
#endif
                var message = (string)_message.GetValue(exception);
                var remoteStackTraceString = (string)_remoteStackTraceString.GetValue(exception);
                var stackTraceString       = (string)_stackTraceString.GetValue(exception);
                var innerException         = _innerException.GetValue(exception);
                StringSerializer.WriteValueImpl(stream, className, session);
                StringSerializer.WriteValueImpl(stream, message, session);
                StringSerializer.WriteValueImpl(stream, remoteStackTraceString, session);
                StringSerializer.WriteValueImpl(stream, stackTraceString, session);
                stream.WriteObjectWithManifest(innerException, session);
            });
            if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index))
            {
                var wrapper = new KnownTypeObjectSerializer(exceptionSerializer, index);
                typeMapping.TryAdd(type, wrapper);
            }
            else
            {
                typeMapping.TryAdd(type, exceptionSerializer);
            }
            return(exceptionSerializer);
        }
        public override ValueSerializer BuildSerializer(Serializer serializer, Type type,
                                                        ConcurrentDictionary <Type, ValueSerializer> typeMapping)
        {
            var ser = new ObjectSerializer(type);

            if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index))
            {
                var wrapper = new KnownTypeObjectSerializer(ser, index);
                typeMapping.TryAdd(type, wrapper);
            }
            else
            {
                typeMapping.TryAdd(type, ser);
            }
            var          elementSerializer        = serializer.GetSerializerByType(typeof(DictionaryEntry));
            var          preserveObjectReferences = serializer.Options.PreserveObjectReferences;
            ObjectReader reader = (stream, session) =>
            {
                var count    = stream.ReadInt32(session);
                var instance = (IDictionary)Activator.CreateInstance(type, count);
                if (preserveObjectReferences)
                {
                    session.TrackDeserializedObject(instance);
                }

                for (var i = 0; i < count; i++)
                {
                    var entry = (DictionaryEntry)stream.ReadObject(session);
                    instance.Add(entry.Key, entry.Value);
                }
                return(instance);
            };

            ObjectWriter writer = (stream, obj, session) =>
            {
                if (preserveObjectReferences)
                {
                    session.TrackSerializedObject(obj);
                }
                var dict = obj as IDictionary;
                // ReSharper disable once PossibleNullReferenceException
                Int32Serializer.WriteValueImpl(stream, dict.Count, session);
                foreach (DictionaryEntry item in dict)
                {
                    stream.WriteObject(item, typeof(DictionaryEntry), elementSerializer,
                                       serializer.Options.PreserveObjectReferences, session);
                    // elementSerializer.WriteValue(stream,item,session);
                }
            };

            ser.Initialize(reader, writer);

            return(ser);
        }
Пример #4
0
        public override ValueSerializer BuildSerializer(Serializer serializer, Type type,
                                                        ConcurrentDictionary <Type, ValueSerializer> typeMapping)
        {
            var arraySerializer = new ObjectSerializer(type);

            var elementType              = type.GetElementType();
            var elementSerializer        = serializer.GetSerializerByType(elementType);
            var preserveObjectReferences = serializer.Options.PreserveObjectReferences;
            //TODO: code gen this part
            ObjectReader reader = (stream, session) =>
            {
                var length = stream.ReadInt32(session);
                var array  = Array.CreateInstance(elementType, length); //create the array
                if (preserveObjectReferences)
                {
                    session.TrackDeserializedObject(array);
                }

                ReadValues(length, stream, session, (dynamic)array);

                return(array);
            };
            ObjectWriter writer = (stream, arr, session) =>
            {
                if (preserveObjectReferences)
                {
                    session.TrackSerializedObject(arr);
                }

                WriteValues((dynamic)arr, stream, elementType, elementSerializer, session);
            };

            arraySerializer.Initialize(reader, writer);

            if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index))
            {
                var wrapper = new KnownTypeObjectSerializer(arraySerializer, index);
                typeMapping.TryAdd(type, wrapper);
            }
            else
            {
                typeMapping.TryAdd(type, arraySerializer);
            }
            return(arraySerializer);
        }
Пример #5
0
        public override ValueSerializer BuildSerializer(Serializer serializer, Type type,
                                                        ConcurrentDictionary <Type, ValueSerializer> typeMapping)
        {
            var arraySerializer = new ObjectSerializer(type);

            var elementType =
                type.GetTypeInfo()
                .GetMethods()
                .Where(methodInfo => methodInfo.Name == "Get")
                .Select(methodInfo => methodInfo.ReturnType)
                .FirstOrDefault();

            var elementSerializer        = serializer.GetSerializerByType(elementType);
            var preserveObjectReferences = serializer.Options.PreserveObjectReferences;

            var arrayRank = type.GetArrayRank();

            //TODO: code gen this part
            ObjectReader reader = CreateReader(preserveObjectReferences, arrayRank, elementType);

            ObjectWriter writer = (stream, arr, session) =>
            {
                if (preserveObjectReferences)
                {
                    session.TrackSerializedObject(arr);
                }

                WriteValues((Array)arr, stream, elementType, elementSerializer, session);
            };

            arraySerializer.Initialize(reader, writer);
            if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index))
            {
                var wrapper = new KnownTypeObjectSerializer(arraySerializer, index);
                typeMapping.TryAdd(type, wrapper);
            }
            else
            {
                typeMapping.TryAdd(type, arraySerializer);
            }
            return(arraySerializer);
        }
Пример #6
0
        public ValueSerializer GetSerializerByType([NotNull] Type type)
        {
            //do we already have a serializer for this type?
            if (_serializers.TryGetValue(type, out var serializer))
            {
                return(serializer);
            }

            //is there a serializer factory that can handle this type?
            foreach (var valueSerializerFactory in Options.ValueSerializerFactories)
            {
                if (valueSerializerFactory.CanSerialize(this, type))
                {
                    return(valueSerializerFactory.BuildSerializer(this, type, _serializers));
                }
            }

            //none of the above, lets create a POCO object serializer
            serializer = new ObjectSerializer(type);
            if (Options.KnownTypesDict.TryGetValue(type, out var index))
            {
                var wrapper = new KnownTypeObjectSerializer((ObjectSerializer)serializer, index);
                if (!_serializers.TryAdd(type, wrapper))
                {
                    return(_serializers[type]);
                }



                try
                {
                    //build the serializer IL code
                    CodeGenerator.BuildSerializer(this, (ObjectSerializer)serializer);
                }
                catch (Exception exp)
                {
                    var invalidSerializer = new UnsupportedTypeSerializer(type, exp.Message);
                    _serializers[type] = invalidSerializer;
                    return(invalidSerializer);
                }
                //just ignore if this fails, another thread have already added an identical serializer
                return(wrapper);
            }
            if (!_serializers.TryAdd(type, serializer))
            {
                return(_serializers[type]);
            }



            try
            {
                //build the serializer IL code
                CodeGenerator.BuildSerializer(this, (ObjectSerializer)serializer);
            }
            catch (Exception exp)
            {
                var invalidSerializer = new UnsupportedTypeSerializer(type, exp.Message);
                _serializers[type] = invalidSerializer;
                return(invalidSerializer);
            }


            //just ignore if this fails, another thread have already added an identical serializer
            return(serializer);
            //add it to the serializer lookup in case of recursive serialization
        }
        public override ValueSerializer BuildSerializer(Serializer serializer, Type type,
                                                        ConcurrentDictionary <Type, ValueSerializer> typeMapping)
        {
            var x = new ObjectSerializer(type);

            if (serializer.Options.KnownTypesDict.TryGetValue(type, out var index))
            {
                var wrapper = new KnownTypeObjectSerializer(x, index);
                typeMapping.TryAdd(type, wrapper);
            }
            else
            {
                typeMapping.TryAdd(type, x);
            }
            var preserveObjectReferences = serializer.Options.PreserveObjectReferences;

            var elementType       = GetEnumerableType(type) ?? typeof(object);
            var elementSerializer = serializer.GetSerializerByType(elementType);

            var typeName        = type.Name;
            var genericSufixIdx = typeName.IndexOf('`');

            typeName = genericSufixIdx != -1 ? typeName.Substring(0, genericSufixIdx) : typeName;
            var creatorType =
                Type.GetType(ImmutableCollectionsNamespace + "." + typeName + ", " + ImmutableCollectionsAssembly);


            var createRangeMethodInfo = creatorType != null
                ? creatorType.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Static)
                                        .First(methodInfo => methodInfo.Name == "CreateRange" && methodInfo.GetParameters().Length == 1)
                : null;

            // If the element type is a generic type and the method located to create the collection instance requires more than one generic type parameter
            // we need to obtain the generic arguments of the element type.
            var genericTypes = elementType.GetTypeInfo().IsGenericType&& createRangeMethodInfo != null && createRangeMethodInfo.GetGenericArguments().Length > 1
                ? elementType.GetTypeInfo().GetGenericArguments()
                : new[] { elementType };

            // if creatorType == null it means that type is probably an interface
            // we propagate null to create mock serializer - it won't be used anyway

            var stackTypeDef   = Type.GetType(ImmutableCollectionsNamespace + ".IImmutableStack`1, " + ImmutableCollectionsAssembly, true);
            var stackInterface = stackTypeDef.MakeGenericType(genericTypes[0]);

            var isStack = stackInterface.IsAssignableFrom(type);

            var createRange = createRangeMethodInfo != null
                ? createRangeMethodInfo.MakeGenericMethod(genericTypes)
                : null;

            ObjectWriter writer = (stream, o, session) =>
            {
                var enumerable = o as ICollection;
                if (enumerable == null)
                {
                    // object can be IEnumerable but not ICollection i.e. ImmutableQueue
                    var e    = (IEnumerable)o;
                    var list = e.Cast <object>().ToList();//

                    enumerable = list;
                }
                Int32Serializer.WriteValueImpl(stream, enumerable.Count, session);
                foreach (var value in enumerable)
                {
                    stream.WriteObject(value, elementType, elementSerializer, preserveObjectReferences, session);
                }
                if (preserveObjectReferences)
                {
                    session.TrackSerializedObject(o);
                }
            };
            ObjectReader reader;

            if (isStack)
            {
                // if we are dealing with stack, we need to apply arguments in reverse order
                reader = (stream, session) =>
                {
                    var count = stream.ReadInt32(session);
                    var items = Array.CreateInstance(elementType, count);
                    for (var i = 0; i < count; i++)
                    {
                        var value = stream.ReadObject(session);
                        items.SetValue(value, count - i - 1);
                    }

                    var instance = createRange.Invoke(null, new object[] { items });
                    if (preserveObjectReferences)
                    {
                        session.TrackDeserializedObject(instance);
                    }
                    return(instance);
                };
            }
            else
            {
                reader = (stream, session) =>
                {
                    var count = stream.ReadInt32(session);
                    var items = Array.CreateInstance(elementType, count);
                    for (var i = 0; i < count; i++)
                    {
                        var value = stream.ReadObject(session);
                        items.SetValue(value, i);
                    }

                    var instance = createRange.Invoke(null, new object[] { items });
                    if (preserveObjectReferences)
                    {
                        session.TrackDeserializedObject(instance);
                    }
                    return(instance);
                };
            }
            x.Initialize(reader, writer);
            return(x);
        }