예제 #1
0
        /// <summary>
        /// Provides the actual implementation for serializing a value of type <see cref="T" />.
        /// </summary>
        /// <param name="value">The value to serialize.</param>
        /// <param name="writer">The writer to serialize with.</param>
        protected override void SerializeImplementation(ref T value, IDataWriter writer)
        {
            var members = FormatterUtilities.GetSerializableMembers(typeof(T), this.OverridePolicy ?? writer.Context.Config.SerializationPolicy);

            for (int i = 0; i < members.Length; i++)
            {
                var  member = members[i];
                Type type;
                var  memberValue = FormatterUtilities.GetMemberValue(member, value);

                if (object.ReferenceEquals(memberValue, null))
                {
                    type = FormatterUtilities.GetContainedType(member);
                }
                else
                {
                    type = memberValue.GetType();
                }

                var serializer = Serializer.Get(type);

                try
                {
                    serializer.WriteValueWeak(member.Name, memberValue, writer);
                }
                catch (Exception ex)
                {
                    writer.Context.Config.DebugContext.LogException(ex);
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Writes the given <see cref="SerializationInfo" /> using the given writer.
        /// </summary>
        /// <param name="info">The <see cref="SerializationInfo" /> to write.</param>
        /// <param name="writer">The writer to use.</param>
        private void WriteSerializationInfo(SerializationInfo info, IDataWriter writer)
        {
            try
            {
                writer.BeginArrayNode(info.MemberCount);

                foreach (var entry in info)
                {
                    try
                    {
                        writer.WriteString("type", writer.Context.Binder.BindToName(entry.ObjectType, writer.Context.Config.DebugContext));
                        var readerWriter = Serializer.Get(entry.ObjectType);
                        readerWriter.WriteValueWeak(entry.Name, entry.Value, writer);
                    }
                    catch (Exception ex)
                    {
                        writer.Context.Config.DebugContext.LogException(ex);
                    }
                }
            }
            finally
            {
                writer.EndArrayNode();
            }
        }
 /// <summary>
 /// Deserializes a value of a given type from the given reader, using the given list of Unity objects for external index reference resolution.
 /// </summary>
 /// <typeparam name="T">The type to deserialize.</typeparam>
 /// <param name="reader">The reader to use.</param>
 /// <param name="referencedUnityObjects">The list of Unity objects to use for external index reference resolution.</param>
 /// <returns>
 /// The deserialized value.
 /// </returns>
 public static T DeserializeValue <T>(IDataReader reader, List <UnityEngine.Object> referencedUnityObjects)
 {
     using (var unityResolver = Cache <UnityReferenceResolver> .Claim())
     {
         unityResolver.Value.SetReferencedUnityObjects(referencedUnityObjects);
         reader.Context.IndexReferenceResolver = unityResolver.Value;
         return(Serializer.Get <T>().ReadValue(reader));
     }
 }
 /// <summary>
 /// Serializes the given value, using the given writer.
 /// </summary>
 /// <typeparam name="T">The type of the value to serialize.</typeparam>
 /// <param name="value">The value to serialize.</param>
 /// <param name="writer">The writer to use.</param>
 /// <param name="unityObjects">A list of the Unity objects which were referenced during serialization.</param>
 public static void SerializeValue <T>(T value, IDataWriter writer, out List <UnityEngine.Object> unityObjects)
 {
     using (var unityResolver = Cache <UnityReferenceResolver> .Claim())
     {
         writer.Context.IndexReferenceResolver = unityResolver.Value;
         Serializer.Get <T>().WriteValue(value, writer);
         writer.FlushToStream();
         unityObjects = unityResolver.Value.GetReferencedUnityObjects();
     }
 }
예제 #5
0
        /// <summary>
        /// Creates and reads into a <see cref="SerializationInfo" /> instance using a given reader and context.
        /// </summary>
        /// <param name="reader">The reader to use.</param>
        /// <returns>
        /// The <see cref="SerializationInfo" /> which was read.
        /// </returns>
        private SerializationInfo ReadSerializationInfo(IDataReader reader)
        {
            string    name;
            EntryType entry = reader.PeekEntry(out name);

            if (entry == EntryType.StartOfArray)
            {
                try
                {
                    long length;
                    reader.EnterArray(out length);

                    SerializationInfo info = new SerializationInfo(typeof(T), reader.Context.FormatterConverter);

                    for (int i = 0; i < length; i++)
                    {
                        Type type = null;
                        entry = reader.PeekEntry(out name);

                        if (entry == EntryType.String && name == "type")
                        {
                            string typeName;
                            reader.ReadString(out typeName);
                            type = reader.Context.Binder.BindToType(typeName, reader.Context.Config.DebugContext);
                        }

                        if (type == null)
                        {
                            reader.SkipEntry();
                            continue;
                        }

                        entry = reader.PeekEntry(out name);

                        var    readerWriter = Serializer.Get(type);
                        object value        = readerWriter.ReadValueWeak(reader);
                        info.AddValue(name, value);
                    }

                    return(info);
                }
                finally
                {
                    reader.ExitArray();
                }
            }

            return(null);
        }
예제 #6
0
        /// <summary>
        /// Provides the actual implementation for deserializing a value of type <see cref="T" />.
        /// </summary>
        /// <param name="value">The uninitialized value to serialize into. This value will have been created earlier using <see cref="BaseFormatter{T}.GetUninitializedObject" />.</param>
        /// <param name="reader">The reader to deserialize with.</param>
        protected override void DeserializeImplementation(ref T value, IDataReader reader)
        {
            // We sadly *must* box so that complex value types get their values properly set by reflection.
            // At least we only box these once.
            object boxedValue = value;

            var members = FormatterUtilities.GetSerializableMembersMap(typeof(T), this.OverridePolicy ?? reader.Context.Config.SerializationPolicy);

            EntryType entryType;
            string    name;

            while ((entryType = reader.PeekEntry(out name)) != EntryType.EndOfNode && entryType != EntryType.EndOfArray && entryType != EntryType.EndOfStream)
            {
                if (string.IsNullOrEmpty(name))
                {
                    reader.Context.Config.DebugContext.LogError("Entry of type \"" + entryType + "\" in node \"" + reader.CurrentNodeName + "\" is missing a name.");
                    reader.SkipEntry();
                    continue;
                }

                MemberInfo member;

                if (members.TryGetValue(name, out member) == false)
                {
                    reader.Context.Config.DebugContext.LogWarning("Lost serialization data for entry \"" + name + "\" of type \"" + entryType + "\"in node \"" + reader.CurrentNodeName + "\".");
                    reader.SkipEntry();
                    continue;
                }

                Type expectedType = FormatterUtilities.GetContainedType(member);

                try
                {
                    var    serializer = Serializer.Get(expectedType);
                    object entryValue = serializer.ReadValueWeak(reader);
                    FormatterUtilities.SetMemberValue(member, boxedValue, entryValue);
                }
                catch (Exception ex)
                {
                    reader.Context.Config.DebugContext.LogException(ex);
                }
            }

            value = (T)boxedValue; // Unbox
        }
 /// <summary>
 /// Deserializes a value from the given reader.
 /// </summary>
 /// <typeparam name="T">The type to deserialize.</typeparam>
 /// <param name="reader">The reader to use.</param>
 /// <returns>The deserialized value.</returns>
 public static T DeserializeValue <T>(IDataReader reader)
 {
     return(Serializer.Get <T>().ReadValue(reader));
 }
 /// <summary>
 /// Deserializes a value from the given reader. This might fail with primitive values, as they don't come with metadata.
 /// </summary>
 /// <param name="reader">The reader to use.</param>
 /// <returns>The deserialized value.</returns>
 public static object DeserializeValueWeak(IDataReader reader)
 {
     return(Serializer.Get <object>().ReadValueWeak(reader));
 }
 /// <summary>
 /// Serializes the given value using the given writer.
 /// </summary>
 /// <typeparam name="T">The type of the value to serialize.</typeparam>
 /// <param name="value">The value to serialize.</param>
 /// <param name="writer">The writer to use.</param>
 public static void SerializeValue <T>(T value, IDataWriter writer)
 {
     Serializer.Get <T>().WriteValue(value, writer);
     writer.FlushToStream();
 }
예제 #10
0
        /// <summary>
        /// Writes a value of type <see cref="T" />.
        /// </summary>
        /// <param name="name">The name of the value to write.</param>
        /// <param name="value">The value to write.</param>
        /// <param name="writer">The writer to use.</param>
        public override void WriteValue(string name, T value, IDataWriter writer)
        {
            var context = writer.Context;

            if (context.Config.SerializationPolicy.AllowNonSerializableTypes == false && typeof(T).IsSerializable == false)
            {
                context.Config.DebugContext.LogError("The type " + typeof(T).Name + " is not marked as serializable.");
                return;
            }

            FireOnSerializedType();

            if (ComplexTypeIsValueType)
            {
                bool endNode = true;

                try
                {
                    writer.BeginStructNode(name, typeof(T));
                    FormatterLocator.GetFormatter <T>(context.Config.SerializationPolicy).Serialize(value, writer);
                }
                catch (SerializationAbortException ex)
                {
                    endNode = false;
                    throw ex;
                }
                finally
                {
                    if (endNode)
                    {
                        writer.EndNode(name);
                    }
                }
            }
            else
            {
                int    id;
                int    index;
                string strId;
                Guid   guid;

                bool endNode = true;

                if (object.ReferenceEquals(value, null))
                {
                    writer.WriteNull(name);
                }
                else if (context.TryRegisterExternalReference(value, out index))
                {
                    writer.WriteExternalReference(name, index);
                }
                else if (context.TryRegisterExternalReference(value, out guid))
                {
                    writer.WriteExternalReference(name, guid);
                }
                else if (context.TryRegisterExternalReference(value, out strId))
                {
                    writer.WriteExternalReference(name, strId);
                }
                else if (context.TryRegisterInternalReference(value, out id))
                {
                    // Get type of actual stored object
                    //
                    // Don't have it as a strongly typed T value, since people can "override" (shadow)
                    // GetType() on derived classes with the "new" operator. By referencing the type
                    // as a System.Object, we ensure the correct GetType() method is always called.
                    //
                    // (Yes, this has actually happened, and this was done to fix it.)

                    Type type = (value as object).GetType();

                    if (ComplexTypeMayBeBoxedValueType && FormatterUtilities.IsPrimitiveType(type)) // It's a boxed primitive type
                    {
                        try
                        {
                            writer.BeginReferenceNode(name, type, id);

                            var serializer = Serializer.Get(type);
                            serializer.WriteValueWeak(value, writer);
                        }
                        catch (SerializationAbortException ex)
                        {
                            endNode = false;
                            throw ex;
                        }
                        finally
                        {
                            if (endNode)
                            {
                                writer.EndNode(name);
                            }
                        }
                    }
                    else
                    {
                        var formatter = FormatterLocator.GetFormatter(type, context.Config.SerializationPolicy);

                        try
                        {
                            writer.BeginReferenceNode(name, type, id);
                            formatter.Serialize(value, writer);
                        }
                        catch (SerializationAbortException ex)
                        {
                            endNode = false;
                            throw ex;
                        }
                        finally
                        {
                            if (endNode)
                            {
                                writer.EndNode(name);
                            }
                        }
                    }
                }
                else
                {
                    writer.WriteInternalReference(name, id);
                }
            }
        }
예제 #11
0
        /// <summary>
        /// Reads a value of type <see cref="T" />.
        /// </summary>
        /// <param name="reader">The reader to use.</param>
        /// <returns>
        /// The value which has been read.
        /// </returns>
        public override T ReadValue(IDataReader reader)
        {
            var context = reader.Context;

            if (context.Config.SerializationPolicy.AllowNonSerializableTypes == false && typeof(T).IsSerializable == false)
            {
                context.Config.DebugContext.LogError("The type " + typeof(T).Name + " is not marked as serializable.");
                return(default(T));
            }

            bool exitNode = true;

            string name;
            var    entry = reader.PeekEntry(out name);

            if (ComplexTypeIsValueType)
            {
                if (entry == EntryType.Null)
                {
                    context.Config.DebugContext.LogWarning("Expecting complex struct of type " + typeof(T).GetNiceFullName() + " but got null value.");
                    reader.ReadNull();
                    return(default(T));
                }
                else if (entry != EntryType.StartOfNode)
                {
                    context.Config.DebugContext.LogWarning("Unexpected entry '" + name + "' of type " + entry.ToString() + ", when " + EntryType.StartOfNode + " was expected. A value has likely been lost.");
                    reader.SkipEntry();
                    return(default(T));
                }

                try
                {
                    Type expectedType = typeof(T);
                    Type serializedType;

                    if (reader.EnterNode(out serializedType))
                    {
                        if (serializedType != expectedType)
                        {
                            if (serializedType != null)
                            {
                                context.Config.DebugContext.LogWarning("Expected complex struct value " + expectedType.Name + " but the serialized value is of type " + serializedType.Name + ".");

                                if (serializedType.IsCastableTo(expectedType))
                                {
                                    object value = FormatterLocator.GetFormatter(serializedType, context.Config.SerializationPolicy).Deserialize(reader);

                                    bool serializedTypeIsNullable = serializedType.IsGenericType && serializedType.GetGenericTypeDefinition() == typeof(Nullable <>);
                                    bool allowCastMethod          = !ComplexTypeIsNullable && !serializedTypeIsNullable;

                                    var castMethod = allowCastMethod ? serializedType.GetCastMethodDelegate(expectedType) : null;

                                    if (castMethod != null)
                                    {
                                        return((T)castMethod(value));
                                    }
                                    else
                                    {
                                        return((T)value);
                                    }
                                }
                                else
                                {
                                    context.Config.DebugContext.LogWarning("Can't cast serialized type " + serializedType.Name + " into expected type " + expectedType.Name + ". Value lost for node '" + name + "'.");
                                    return(default(T));
                                }
                            }
                            else
                            {
                                context.Config.DebugContext.LogWarning("Expected complex struct value " + expectedType.Name + " but the serialized type could not be resolved.");
                                return(default(T));
                            }
                        }
                        else
                        {
                            return(FormatterLocator.GetFormatter <T>(context.Config.SerializationPolicy).Deserialize(reader));
                        }
                    }
                    else
                    {
                        context.Config.DebugContext.LogError("Failed to enter node '" + name + "'.");
                        return(default(T));
                    }
                }
                catch (SerializationAbortException ex)
                {
                    exitNode = false;
                    throw ex;
                }
                catch (Exception ex)
                {
                    context.Config.DebugContext.LogException(ex);
                    return(default(T));
                }
                finally
                {
                    if (exitNode)
                    {
                        reader.ExitNode();
                    }
                }
            }
            else
            {
                switch (entry)
                {
                case EntryType.Null:
                {
                    reader.ReadNull();
                    return(default(T));
                }

                case EntryType.ExternalReferenceByIndex:
                {
                    int index;
                    reader.ReadExternalReference(out index);

                    object value = context.GetExternalObject(index);

                    try
                    {
                        return((T)value);
                    }
                    catch (InvalidCastException)
                    {
                        context.Config.DebugContext.LogWarning("Can't cast external reference type " + value.GetType().Name + " into expected type " + typeof(T).Name + ". Value lost for node '" + name + "'.");
                        return(default(T));
                    }
                }

                case EntryType.ExternalReferenceByGuid:
                {
                    Guid guid;
                    reader.ReadExternalReference(out guid);

                    object value = context.GetExternalObject(guid);

                    try
                    {
                        return((T)value);
                    }
                    catch (InvalidCastException)
                    {
                        context.Config.DebugContext.LogWarning("Can't cast external reference type " + value.GetType().Name + " into expected type " + typeof(T).Name + ". Value lost for node '" + name + "'.");
                        return(default(T));
                    }
                }

                case EntryType.ExternalReferenceByString:
                {
                    string id;
                    reader.ReadExternalReference(out id);

                    object value = context.GetExternalObject(id);

                    try
                    {
                        return((T)value);
                    }
                    catch (InvalidCastException)
                    {
                        context.Config.DebugContext.LogWarning("Can't cast external reference type " + value.GetType().Name + " into expected type " + typeof(T).Name + ". Value lost for node '" + name + "'.");
                        return(default(T));
                    }
                }

                case EntryType.InternalReference:
                {
                    int id;
                    reader.ReadInternalReference(out id);

                    object value = context.GetInternalReference(id);

                    try
                    {
                        return((T)value);
                    }
                    catch (InvalidCastException)
                    {
                        context.Config.DebugContext.LogWarning("Can't cast internal reference type " + value.GetType().Name + " into expected type " + typeof(T).Name + ". Value lost for node '" + name + "'.");
                        return(default(T));
                    }
                }

                case EntryType.StartOfNode:
                {
                    try
                    {
                        Type expectedType = typeof(T);
                        Type serializedType;
                        int  id;

                        if (reader.EnterNode(out serializedType))
                        {
                            id = reader.CurrentNodeId;

                            T result;

                            if (serializedType != null && expectedType != serializedType)         // We have type metadata different from the expected type
                            {
                                bool success     = false;
                                var  isPrimitive = FormatterUtilities.IsPrimitiveType(serializedType);

                                bool assignableCast;

                                if (ComplexTypeMayBeBoxedValueType && isPrimitive)
                                {
                                    // It's a boxed primitive type, so simply read that straight and register success
                                    var serializer = Serializer.Get(serializedType);
                                    result  = (T)serializer.ReadValueWeak(reader);
                                    success = true;
                                }
                                else if ((assignableCast = expectedType.IsAssignableFrom(serializedType)) || serializedType.HasCastDefined(expectedType, false))
                                {
                                    try
                                    {
                                        object value;

                                        if (isPrimitive)
                                        {
                                            var serializer = Serializer.Get(serializedType);
                                            value = serializer.ReadValueWeak(reader);
                                        }
                                        else
                                        {
                                            var alternateFormatter = FormatterLocator.GetFormatter(serializedType, context.Config.SerializationPolicy);
                                            value = alternateFormatter.Deserialize(reader);
                                        }

                                        if (assignableCast)
                                        {
                                            result = (T)value;
                                        }
                                        else
                                        {
                                            var castMethod = serializedType.GetCastMethodDelegate(expectedType);

                                            if (castMethod != null)
                                            {
                                                result = (T)castMethod(value);
                                            }
                                            else
                                            {
                                                // Let's just give it a go anyways
                                                result = (T)value;
                                            }
                                        }

                                        success = true;
                                    }
                                    catch (SerializationAbortException ex)
                                    {
                                        exitNode = false;
                                        throw ex;
                                    }
                                    catch (InvalidCastException)
                                    {
                                        success = false;
                                        result  = default(T);
                                    }
                                }
                                else
                                {
                                    // We couldn't cast or use the type, but we still have to deserialize it and register
                                    // the reference so the reference isn't lost if it is referred to further down
                                    // the data stream.

                                    var    alternateFormatter = FormatterLocator.GetFormatter(serializedType, context.Config.SerializationPolicy);
                                    object value = alternateFormatter.Deserialize(reader);

                                    if (id >= 0)
                                    {
                                        context.RegisterInternalReference(id, value);
                                    }

                                    result = default(T);
                                }

                                if (!success)
                                {
                                    // We can't use this
                                    context.Config.DebugContext.LogWarning("Can't cast serialized type " + serializedType.Name + " into expected type " + expectedType.Name + ". Value lost for node '" + name + "'.");
                                    result = default(T);
                                }
                            }
                            else if (ComplexTypeIsAbstract)
                            {
                                result = default(T);
                            }
                            else
                            {
                                result = FormatterLocator.GetFormatter <T>(context.Config.SerializationPolicy).Deserialize(reader);
                            }

                            if (id >= 0)
                            {
                                context.RegisterInternalReference(id, result);
                            }

                            return(result);
                        }
                        else
                        {
                            context.Config.DebugContext.LogError("Failed to enter node '" + name + "'.");
                            return(default(T));
                        }
                    }
                    catch (SerializationAbortException ex)
                    {
                        exitNode = false;
                        throw ex;
                    }
                    catch (Exception ex)
                    {
                        context.Config.DebugContext.LogException(ex);
                        return(default(T));
                    }
                    finally
                    {
                        if (exitNode)
                        {
                            reader.ExitNode();
                        }
                    }
                }

                //
                // The below cases are for when we expect an object, but have
                // serialized a straight primitive type. In such cases, we can
                // often box the primitive type as an object.
                //
                // Sadly, the exact primitive type might be lost in case of
                // integer and floating points numbers, as we don't know what
                // type to expect.
                //
                // To be safe, we read and box the most precise type available.
                //

                case EntryType.Boolean:
                {
                    if (!ComplexTypeMayBeBoxedValueType)
                    {
                        goto default;
                    }

                    bool value;
                    reader.ReadBoolean(out value);
                    return((T)(object)value);
                }

                case EntryType.FloatingPoint:
                {
                    if (!ComplexTypeMayBeBoxedValueType)
                    {
                        goto default;
                    }

                    double value;
                    reader.ReadDouble(out value);
                    return((T)(object)value);
                }

                case EntryType.Integer:
                {
                    if (!ComplexTypeMayBeBoxedValueType)
                    {
                        goto default;
                    }

                    long value;
                    reader.ReadInt64(out value);
                    return((T)(object)value);
                }

                case EntryType.String:
                {
                    if (!ComplexTypeMayBeBoxedValueType)
                    {
                        goto default;
                    }

                    string value;
                    reader.ReadString(out value);
                    return((T)(object)value);
                }

                case EntryType.Guid:
                {
                    if (!ComplexTypeMayBeBoxedValueType)
                    {
                        goto default;
                    }

                    Guid value;
                    reader.ReadGuid(out value);
                    return((T)(object)value);
                }

                default:

                    // Lost value somehow
                    context.Config.DebugContext.LogWarning("Unexpected entry of type " + entry.ToString() + ", when a reference or node start was expected. A value has been lost.");
                    reader.SkipEntry();
                    return(default(T));
                }
            }
        }
예제 #12
0
        /// <summary>
        /// Skips the next entry value, unless it is an <see cref="EntryType.EndOfNode"/> or an <see cref="EntryType.EndOfArray"/>. If the next entry value is an <see cref="EntryType.StartOfNode"/> or an <see cref="EntryType.StartOfArray"/>, all of its contents will be processed, deserialized and registered in the deserialization context, so that internal reference values are not lost to entries further down the stream.
        /// </summary>
        public virtual void SkipEntry()
        {
            var peekedEntry = this.PeekEntry();

            if (peekedEntry == EntryType.StartOfNode)
            {
                Type type;

                bool exitNode = true;

                this.EnterNode(out type);

                try
                {
                    if (type != null)
                    {
                        // We have the necessary metadata to read this type, and register all of its reference values (perhaps including itself) in the serialization context
                        // Sadly, we have no choice but to risk boxing of structs here
                        // Luckily, this is a rare case

                        if (FormatterUtilities.IsPrimitiveType(type))
                        {
                            // It is a boxed primitive type; we read the value and register it
                            var    serializer = Serializer.Get(type);
                            object value      = serializer.ReadValueWeak(this);

                            if (this.CurrentNodeId >= 0)
                            {
                                this.Context.RegisterInternalReference(this.CurrentNodeId, value);
                            }
                        }
                        else
                        {
                            var    formatter = FormatterLocator.GetFormatter(type, this.Context.Config.SerializationPolicy);
                            object value     = formatter.Deserialize(this);

                            if (this.CurrentNodeId >= 0)
                            {
                                this.Context.RegisterInternalReference(this.CurrentNodeId, value);
                            }
                        }
                    }
                    else
                    {
                        // We have no metadata, and reference values might be lost
                        // We must read until a node on the same level terminates
                        while (true)
                        {
                            peekedEntry = this.PeekEntry();

                            if (peekedEntry == EntryType.EndOfStream)
                            {
                                break;
                            }
                            else if (peekedEntry == EntryType.EndOfNode)
                            {
                                break;
                            }
                            else if (peekedEntry == EntryType.EndOfArray)
                            {
                                this.ReadToNextEntry(); // Consume end of arrays that we can potentially get stuck on
                            }
                            else
                            {
                                this.SkipEntry();
                            }
                        }
                    }
                }
                catch (SerializationAbortException ex)
                {
                    exitNode = false;
                    throw ex;
                }
                finally
                {
                    if (exitNode)
                    {
                        this.ExitNode();
                    }
                }
            }
            else if (peekedEntry == EntryType.StartOfArray)
            {
                // We must read until an array on the same level terminates
                this.ReadToNextEntry(); // Consume start of array

                while (true)
                {
                    peekedEntry = this.PeekEntry();

                    if (peekedEntry == EntryType.EndOfStream)
                    {
                        break;
                    }
                    else if (peekedEntry == EntryType.EndOfArray)
                    {
                        this.ReadToNextEntry(); // Consume end of array and break
                        break;
                    }
                    else if (peekedEntry == EntryType.EndOfNode)
                    {
                        this.ReadToNextEntry(); // Consume end of nodes that we can potentially get stuck on
                    }
                    else
                    {
                        this.SkipEntry();
                    }
                }
            }
            else if (peekedEntry != EntryType.EndOfArray && peekedEntry != EntryType.EndOfNode) // We can't skip end of arrays and end of nodes
            {
                this.ReadToNextEntry();                                                         // We can just skip a single value entry
            }
        }
예제 #13
0
 /// <summary>
 /// Gets a <see cref="Serializer"/> for type T.
 /// </summary>
 /// <typeparam name="T">The type to get a <see cref="Serializer"/> for.</typeparam>
 /// <returns>A <see cref="Serializer"/> for type T.</returns>
 public static Serializer <T> Get <T>()
 {
     return((Serializer <T>)Serializer.Get(typeof(T)));
 }
예제 #14
0
        /// <summary>
        /// Writes a value of type <see cref="T" />.
        /// </summary>
        /// <param name="name">The name of the value to write.</param>
        /// <param name="value">The value to write.</param>
        /// <param name="writer">The writer to use.</param>
        public override void WriteValue(string name, T value, IDataWriter writer)
        {
            var context = writer.Context;

            if (context.Config.SerializationPolicy.AllowNonSerializableTypes == false && typeof(T).IsSerializable == false)
            {
                context.Config.DebugContext.LogError("The type " + typeof(T).Name + " is not marked as serializable.");
                return;
            }

            FireOnSerializedType();

            if (typeof(T).IsValueType)
            {
                bool endNode = true;

                try
                {
                    writer.BeginStructNode(name, typeof(T));
                    FormatterLocator.GetFormatter <T>(context.Config.SerializationPolicy).Serialize(value, writer);
                }
                catch (SerializationAbortException ex)
                {
                    endNode = false;
                    throw ex;
                }
                finally
                {
                    if (endNode)
                    {
                        writer.EndNode(name);
                    }
                }
            }
            else
            {
                int    id;
                int    index;
                string strId;
                Guid   guid;

                bool endNode = true;

                if (object.ReferenceEquals(value, null))
                {
                    writer.WriteNull(name);
                }
                else if (context.TryRegisterExternalReference(value, out index))
                {
                    writer.WriteExternalReference(name, index);
                }
                else if (context.TryRegisterExternalReference(value, out guid))
                {
                    writer.WriteExternalReference(name, guid);
                }
                else if (context.TryRegisterExternalReference(value, out strId))
                {
                    writer.WriteExternalReference(name, strId);
                }
                else if (context.TryRegisterInternalReference(value, out id))
                {
                    Type type = value.GetType();                                         // Get type of actual stored object

                    if (ComplexTypeIsObject && FormatterUtilities.IsPrimitiveType(type)) // It's a boxed primitive type
                    {
                        try
                        {
                            writer.BeginReferenceNode(name, type, id);

                            var serializer = Serializer.Get(type);
                            serializer.WriteValueWeak(value, writer);
                        }
                        catch (SerializationAbortException ex)
                        {
                            endNode = false;
                            throw ex;
                        }
                        finally
                        {
                            if (endNode)
                            {
                                writer.EndNode(name);
                            }
                        }
                    }
                    else
                    {
                        var formatter = FormatterLocator.GetFormatter(type, context.Config.SerializationPolicy);

                        try
                        {
                            writer.BeginReferenceNode(name, type, id);
                            formatter.Serialize(value, writer);
                        }
                        catch (SerializationAbortException ex)
                        {
                            endNode = false;
                            throw ex;
                        }
                        finally
                        {
                            if (endNode)
                            {
                                writer.EndNode(name);
                            }
                        }
                    }
                }
                else
                {
                    writer.WriteInternalReference(name, id);
                }
            }
        }