我有一个代表数十亿位的RoaringBitmap。它是位图,它是更快/更紧凑的BitArray版本,并且是非托管的。它确实实现了IEnumerable,但更像扩展以获得位置,我不打算复制它们的整个回购来修复实现。以紧凑的形式,它大约需要100字节,以IEnumerable - 1 GB扩展.
我尝试在代理程序中使用转换器,但得到了异常:
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序列化背后的逻辑,因为它可能是无限的,可能是一个生成器,或者是太大(就像我的例子)。
发布于 2022-06-14 20:23:26
找到一个解决方案,只需将其添加到模型中:
var bmModel = model.Add(typeof(RoaringBitmap), false);
bmModel.IgnoreListHandling = true;
bmModel.SetSurrogate(typeof(RoaringBitmapSurrogate));更新
按照@MarcGravell的建议,我最终使用了ISerializer接口(它仍然抱怨IEnumerable,因此我将标志设置为忽略此行为,但不再存在代理类):
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));
}
}https://stackoverflow.com/questions/72622797
复制相似问题