首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在protobuf中序列化复杂的IEnumerable类?

如何在protobuf中序列化复杂的IEnumerable类?
EN

Stack Overflow用户
提问于 2022-06-14 20:06:13
回答 1查看 99关注 0票数 1

我有一个代表数十亿位的RoaringBitmap。它是位图,它是更快/更紧凑的BitArray版本,并且是非托管的。它确实实现了IEnumerable,但更像扩展以获得位置,我不打算复制它们的整个回购来修复实现。以紧凑的形式,它大约需要100字节,以IEnumerable - 1 GB扩展.

我尝试在代理程序中使用转换器,但得到了异常:

代码语言:javascript
复制
public static class ProtobufSerializer
{
    [ProtoContract]
    public sealed class RoaringBitmapSurrogate
    {
        [ProtoMember(1, OverwriteList = true)]
        public byte[] Data { get; set; }

        private const SerializationFormat Format = SerializationFormat.Portable;

        [ProtoConverter]
        public static RoaringBitmapSurrogate Convert(RoaringBitmap obj)
        {
            if (obj == null)
                return null;
            return new RoaringBitmapSurrogate { Data = obj.Serialize(Format) };
        }
        [ProtoConverter]
        public static RoaringBitmap Convert(RoaringBitmapSurrogate obj)
        {
            if(obj == null)
                return null;
            return RoaringBitmap.Deserialize(obj.Data, Format);
        }
    }

    static ProtobufSerializer()
    {
        var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
        //model.Add(typeof(RoaringBitmapSurrogate), true);
        model.Add(typeof(RoaringBitmap), false).SetSurrogate(typeof(RoaringBitmapSurrogate));
    }


    public static byte[] Serialize<T>(T obj)
    {
        var ms = new MemoryStream();
        Serializer.Serialize(ms, obj);
        return ms.ToArray();
    }

    public static T Deserialize<T>(byte[] data)
    {
        return Serializer.Deserialize<T>(new MemoryStream(data));
    }
}

System.InvalidOperationException :对于声明为CRoaring.RoaringBitmap的重复数据,底层集合(CRoaring.RoaringBitmap)必须实现ICollection,且不能声明为只读;可以使用替代(更有异国情调的)集合,但必须使用其众所周知的形式声明(例如,可以将成员声明为ImmutableHashSet)。

如何在protobuf-net?中序列化显然,序列化IEnumerable是愚蠢的。总的来说,我担心IEnumerable序列化背后的逻辑,因为它可能是无限的,可能是一个生成器,或者是太大(就像我的例子)。

EN

回答 1

Stack Overflow用户

发布于 2022-06-14 20:23:26

找到一个解决方案,只需将其添加到模型中:

代码语言:javascript
复制
        var bmModel = model.Add(typeof(RoaringBitmap), false);
        bmModel.IgnoreListHandling = true;
        bmModel.SetSurrogate(typeof(RoaringBitmapSurrogate));

更新

按照@MarcGravell的建议,我最终使用了ISerializer接口(它仍然抱怨IEnumerable,因此我将标志设置为忽略此行为,但不再存在代理类):

代码语言:javascript
复制
public static class ProtobufSerializer
{
    private sealed class RoaringBitmapSerializer : ISerializer<RoaringBitmap>
    {
        private const int MaxRoaringBitmapSize = 8 * 1024;//suffice for my needs, but not yours.
        private static readonly ArrayPool<byte> Pool = ArrayPool<byte>.Shared;

        private const SerializationFormat Format = SerializationFormat.Portable;

        public RoaringBitmap Read(ref ProtoReader.State state, RoaringBitmap value)
        {
            var buffer = Pool.Rent(MaxRoaringBitmapSize);
            try
            {
                var read = state.ReadBytes(buffer);
                return RoaringBitmap.Deserialize(read.ToArray(), Format);
            }
            finally
            {
                Pool.Return(buffer);
            }
        }

        public void Write(ref ProtoWriter.State state, RoaringBitmap value)
        {
            state.WriteBytes(value.Serialize(Format));
        }

        public SerializerFeatures Features => SerializerFeatures.CategoryScalar | SerializerFeatures.WireTypeString;
    }

    static ProtobufSerializer()
    {
        var model = ProtoBuf.Meta.RuntimeTypeModel.Default;
        var bmModel = model.Add(typeof(RoaringBitmap), false);
        bmModel.SerializerType = typeof(RoaringBitmapSerializer);
        bmModel.IgnoreListHandling = true;
    }


    public static byte[] Serialize<T>(T obj)
    {
        var ms = new MemoryStream();
        Serializer.Serialize(ms, obj);
        return ms.ToArray();
    }

    public static T Deserialize<T>(byte[] data)
    {
        return Serializer.Deserialize<T>(new MemoryStream(data));
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72622797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档