MessagePack of C# (unity)--02

Advanced API (MessagePackSerializer)

The MessagePackSerializer class is the entry point of MessagePack for C#. Static methods constitute the main API of MessagePack for C#.

API Description
Serialize<T> Serialize an object graph into MessagePack binary blocks. A Stream can be obtained using the async variant. There are also non-generic overloads available.
Deserialize<T> Convert MessagePack binary to object graph. Asynchronous variants available for Stream. There are also non-generic overloads available.
SerializeToJson Serialize MessagePack-compatible object graph to JSON instead of MessagePack. This is helpful for debugging.
ConvertToJson Convert MessagePack binary to JSON. This is helpful for debugging
ConvertFromJson Convert JSON to MessagePack binary.

MessagePack for C# basically uses IBufferWriter <byte> for serialization and ReadOnlySequence <byte> or Memory <byte> for deserialization. Convenience method overloads are provided to easily work with common buffer types and .NET Stream classes, but these convenience overloads require copying the buffer once, so there is some overhead.

The high-level API uses memory pools internally to avoid unnecessary memory allocations. If the result size is less than 64K, GC memory is allocated only for the returned bytes.

Each serialize/deserialize method optionally accepts a MessagePackSerializerOptions parameter, which can be used to specify a custom IFormatterResolver to use or activate LZ4 compression support.

Multiple MessagePack structures on a single Stream

To deserialize a stream containing multiple consecutive MessagePack data structures, you can use the MessagePackStreamReader class to efficiently identify the ReadOnlySequence<byte> of each data structure and deserialize it. For example:

static async Task<List<T>> DeserializeListFromStreamAsync<T>(Stream stream, CancellationToken cancellationToken)
{
    var dataStructures = new List<T>();
    using (var streamReader = new MessagePackStreamReader(stream))
    {
        while (await streamReader.ReadAsync(cancellationToken) is ReadOnlySequence<byte> msgpack)
        {
            dataStructures.Add(MessagePackSerializer.Deserialize<T>(msgpack, cancellationToken: cancellationToken));
        }
    }

    return dataStructures;
}

Low-level API (IMessagePackFormatter<T>)

The IMessagePackFormatter<T> interface is responsible for serializing a unique type. For example, Int32Formatter: IMessagePackFormatter<Int32> represents the Int32 MessagePack serializer

public interface IMessagePackFormatter<T>
{
    void Serialize(ref MessagePackWriter writer, T value, MessagePackSerializerOptions options);
    T Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options);
}

There are many built-in formatters located under MessagePack.Formatters. Your custom types are usually automatically supported, using dynamic code generation to generate the new IMessagePackFormatter<T> type's built-in type parser. For platforms that do not support this feature, please see our AOT code generation support.

However, some types (especially those provided by third-party libraries or the runtime itself) cannot be annotated appropriately, and contract-less serialization can produce inefficient or even erroneous results. For greater control over the serialization of such custom types, write your own IMessagePackFormatter<T> implementation. Below is an example of such a custom formatter implementation. Note that it uses the original API, which is described in the next section.

/// <summary>Serializes a <see cref="FileInfo" /> by its full path as a string.</summary>
public class FileInfoFormatter : IMessagePackFormatter<FileInfo>
{
    public void Serialize(
      ref MessagePackWriter writer, FileInfo value, MessagePackSerializerOptions options)
    {
        if (value == null)
        {
            writer.WriteNil();
            return;
        }

        writer.WriteString(value.FullName);
    }

    public FileInfo Deserialize(
      ref MessagePackReader reader, MessagePackSerializerOptions options)
    {
        if (reader.TryReadNil())
        {
            return null;
        }

        options.Security.DepthStep(ref reader);

        var path = reader.ReadString();

        reader.Depth--;
        return new FileInfo(path);
    }
}

The DepthStep and Depth-- statements provide a layer of security that can lead to a denial of service attack when deserializing untrusted data, sending packet data that causes a stack overflow exception and crashes the process. These two statements should surround the main part of any IMessagePackFormatter<T>.Deserialize method.

Note: A message pack formatter must read and write a data structure. In the above example we are just reading or writing a string. If you have multiple elements to write, you must add a map or array header in front. The entire map/array must be read during deserialization. For example:

public class MySpecialObjectFormatter : IMessagePackFormatter<MySpecialObject>
{
    public void Serialize(
      ref MessagePackWriter writer, MySpecialObject value, MessagePackSerializerOptions options)
    {
        if (value == null)
        {
            writer.WriteNil();
            return;
        }

        writer.WriteArrayHeader(2);
        writer.WriteString(value.FullName);
        writer.WriteString(value.Age);
    }

    public MySpecialObject Deserialize(
      ref MessagePackReader reader, MessagePackSerializerOptions options)
    {
        if (reader.TryReadNil())
        {
            return null;
        }

        options.Security.DepthStep(ref reader);

        string fullName = null;
        int age = 0;

        // Loop over *all* array elements independently of how many we expect,
        // since if we're serializing an older/newer version of this object it might
        // vary in number of elements that were serialized, but the contract of the formatter
        // is that exactly one data structure must be read, regardless.
        // Alternatively, we could check that the size of the array/map is what we expect
        // and throw if it is not.
        int count = reader.ReadArrayHeader();
        for (int i = 0; i < count; i++)
        {
            switch (i)
            {
                case 0:
                    fullName = reader.ReadString();
                    break;
                case 1:
                    age = reader.ReadInt32();
                    break;
                default:
                    reader.Skip();
                    break;
            }
        }

        reader.Depth--;
        return new MySpecialObject(fullName, age);
    }
}

unity support

The minimum supported version of Unity is 2018.3, and the API compatibility level supports both .NET 4.x and .NET Standard 2.0.

The unitypackage can be installed from the Release page. If the build targets .NET Framework 4.x and is running on mono, you can use it directly. But if the build target is IL2CPP, Dynamic***Resolver cannot be used, so pre-code generation needs to be used. See the pre-code generation section.

MessagePack for C# includes some additional System.*.dll libraries originally provided in NuGet. They are located under the Plugins folder. If other packages use these libraries (such as the Unity Collections package that uses System.Runtime.CompilerServices.Unsafe.dll), to avoid conflicts, delete the DLL under Plugins.

Currently CompositeResolver.Create does not work on IL2Cpp, so it is recommended to use StaticCompositeResolver.Instance.Register.

In Unity, MessagePackSerializer can use the built-in extension UnityResolver to convert Vector2, Vector3, Vector4, Quaternion, Color, Bounds, Rect, AnimationCurve, Keyframe, Matrix4x4, Gradient, Color32, RectOffset, LayerMask, Vector2Int, Vector3Int, RangeInt, RectInt, BoundsInt and its Nullable, array and list type serialization. It is included in StandardResolver by default.

MessagePack for C# has an additional unsafe extension. UnsafeBlitResolver is a special parser for extremely fast but unsafe serialization/deserialization of arrays of structures

Guess you like

Origin blog.csdn.net/Edision_li/article/details/134462141