Git Product home page Git Product logo

Comments (2)

yfakariya avatar yfakariya commented on August 17, 2024

Unfortunately, generics of value types are poorly supported in Unity runtime itself. Using subclass like Int32List : List<int> might help you.

from msgpack-cli.

shuidong avatar shuidong commented on August 17, 2024

Thank you for your advice.
Temporarily I make such a solution. I write it here, maybe would helpful to other man.

For this class:

public class MyData
{
    public List<int> a = new List<int>();
        //ryaku
}

①First, write a Serializer class ,

public class ListintSerializer : MsgPack.Serialization.MessagePackSerializer<List<int>>
{

    public ListintSerializer(SerializationContext ownerContext)
        : base(ownerContext)
    {
    }

    protected override void PackToCore(Packer packer, List<int> objectTree0)
    {
        int[] objectTree = objectTree0.ToArray();
        packer.PackArrayHeader(objectTree.Length);
        foreach (var item in objectTree)
        {
            packer.Pack(item);
        }
    }

    protected override List<int> UnpackFromCore(Unpacker unpacker)
    {
        if (!unpacker.IsArrayHeader)
        {
            throw SerializationExceptions.NewIsNotArrayHeader();
        }

        var count = UnpackHelpers.GetItemsCount(unpacker);
        var result = new System.Int32[count];

        if (!unpacker.IsArrayHeader)
        {
            throw SerializationExceptions.NewIsNotArrayHeader();
        }

        for (int i = 0; i < count; i++)
        {
            System.Int32 item;
            if (!unpacker.ReadInt32(out item))
            {
                throw SerializationExceptions.NewMissingItem(i);
            }

            result[i] = item;
        }
        return new List<int>(result);
    }
}

Now, once system encode/decode List<int> it will call pack/unpack method written by ourself, this avoid the disadvantages of Unity(IOS platform) poor generic support.

②Then, we register these serializers.

SerializationContext _context = new SerializationContext();
_context.Serializers.RegisterOverride(new ListintSerializer(_context));
_context.Serializers.RegisterOverride(new MyDataSerializerByMpuEXE(_context));

The MyDataSerializerByMpuEXE class was generated by mpu.exe as this↓

mono mpu.exe -s ${path_of_MyData_cs} 

Encode/decode of primitive types are similar.
I wrote ListdoubleSerializer,ListfloatSerializer,ListlongSerializer,ListstringSerializer in the same way.
The key is the pack & unpack method, for example , to Long type there is the code:

protected override void PackToCore(Packer packer, List<long> objectTree0)
    {
        long[] objectTree = objectTree0.ToArray();
        packer.PackArrayHeader(objectTree.Length);
        foreach (var item in objectTree)
        {
            packer.Pack(item);
        }
    }

    protected override List<long> UnpackFromCore(Unpacker unpacker)
    {
        if (!unpacker.IsArrayHeader)
        {
            throw SerializationExceptions.NewIsNotArrayHeader();
        }

        var count = UnpackHelpers.GetItemsCount(unpacker);
        var result = new System.Int64[count];

        if (!unpacker.IsArrayHeader)
        {
            throw SerializationExceptions.NewIsNotArrayHeader();
        }

        for (int i = 0; i < count; i++)
        {
            System.Int64 item;
            if (!unpacker.ReadInt64(out item))
            {
                throw SerializationExceptions.NewMissingItem(i);
            }

            result[i] = item;
        }
        return new List<long>(result);
    }

If the generic type is an class(not primitive type ), code has a little different.
For this class:

public class MyData2
{
    public List<innerData> a = new List<innerData>();

   public class innerData
   {
        public List<int> a = new List<int>();
        public innerData(){}
    }
}

The serialize would be look like this:

public class ListMyData2_innerDataSerializer : MsgPack.Serialization.MessagePackSerializer<List<MyData2.innerData>>
{

    public ListMyData2_innerDataSerializer(SerializationContext ownerContext)
        : base(ownerContext)
    {
    }

    protected override void PackToCore(Packer packer, List<MyData2.innerData> objectTree0)
    {
//SerializerMgr is my manger class, don't care.
        MessagePackSerializer<MyData2.innerData> _itemSerializer = SerializerMgr.Instance._context.GetSerializer<MyData2.innerData>();
        MyData2.innerData[] objectTree = objectTree0.ToArray();
        packer.PackArrayHeader(objectTree.Length);
        foreach (var item in objectTree)
        {
            _itemSerializer.PackTo(packer, item);
        }
    }

    protected override List<MyData2.innerData> UnpackFromCore(Unpacker unpacker)
    {
        MessagePackSerializer<MyData2.innerData> _itemSerializer = SerializerMgr.Instance._context.GetSerializer<MyData2.innerData>();
        if (!unpacker.IsArrayHeader)
        {
            throw SerializationExceptions.NewIsNotArrayHeader();
        }

        var count = UnpackHelpers.GetItemsCount(unpacker);
        var result = new List<MyData2.innerData>();

        if (!unpacker.IsArrayHeader)
        {
            throw SerializationExceptions.NewIsNotArrayHeader();
        }

        for (int i = 0; i < count; i++)
        {
            if (!unpacker.Read())
            {
                throw SerializationExceptions.NewMissingItem(i);
            }

            MyData2.innerData item;
            if (!unpacker.IsArrayHeader && !unpacker.IsMapHeader)
            {
                item = _itemSerializer.UnpackFrom(unpacker);
            }
            else
            {
                using (var subtreeUnpacker = unpacker.ReadSubtree())
                {
                    item = _itemSerializer.UnpackFrom(subtreeUnpacker);
                }
            }

            result.Add(item);
        }
        return result;
    }
}

Similarly, we need register our serializers.

_context.Serializers.RegisterOverride(new ListdoubleSerializer(_context));
_context.Serializers.RegisterOverride(new ListfloatSerializer(_context));
_context.Serializers.RegisterOverride(new ListintSerializer(_context));
_context.Serializers.RegisterOverride(new ListlongSerializer(_context));
_context.Serializers.RegisterOverride(new ListstringSerializer(_context));
_context.Serializers.RegisterOverride(new ListMyData2_innerDataSerializer (_context));

Thanks
shuidong

from msgpack-cli.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.