序列化/反序列化 Protocol Buffers

3
我目前正在使用Protocol Buffers(版本3 C#)进行工作。我正在向不同的服务发送消息,并尝试将某些消息中存储的数据保存到数据库中(可以是任何类型)。
问题在于,字节[]被创建为类型ByteString,List 被创建为RepeatedField 。现在我对它们的问题是,我还没有成功地将它们序列化或反序列化100%。
基本类型很好用,但Protocol Buffers自己的类型可能会有挑战。
我尝试了AutoMapper并创建了映射,使ByteString可以进行序列化/反序列化,但由于RepeatedField是只读的,并且具有私有setter并且不能在构造函数中设置,因此这是困难的。
我无法使AutoMapper正确地映射到它,如果在途中出现更多麻烦,我也不会感到惊讶,我想知道是否有更简单的方法将消息保存在数据库中?
我已经阅读了旧版本的protobuf,那里(如果我没记错的话)有所谓的构建器,您可以访问每个消息的属性,这些属性是可变的,并且会使序列化/反序列化更加容易。或者是否有一种更明显的方法来访问数据并将其存储在数据库中,我只是看不到?
我理解消息为什么是不可变的,但是是否真的没有直接的方法将包含的数据保存到数据库中?感觉像一个重要的功能。
PS:我知道有一个protobuf-net解决方案可以处理序列化/反序列化,但它仅支持protobuf v.2,而我严重依赖于v.3功能,例如Any。
2个回答

7

我已经使用AutoMapper 6.1.1来映射到protobuf 3的RepeatedField<>。我相信反射可以得到改进,但是AutoMapper配置如下:

void Configure(IMapperConfigurationExpression cfg)
{
    cfg.CreateMap<ProtoThings, HasListOfThings>().ReverseMap();

    bool IsToRepeatedField(PropertyMap pm)
    {
        if (pm.DestinationPropertyType.IsConstructedGenericType)
        {
            var destGenericBase = pm.DestinationPropertyType.GetGenericTypeDefinition();
            return destGenericBase == typeof(RepeatedField<>);
        }
        return false;
    }
    cfg.ForAllPropertyMaps(IsToRepeatedField, (propertyMap, opts) => opts.UseDestinationValue());
}

太好了!我已经很久没有涉足那个项目了,但出于好奇心,我一定会去看看的。我的解决方案是下载protoc客户端的源代码,并更改代码生成器,以便所有重复字段都有公共设置器(如果我没记错的话)。不过,如果你的解决方案可行的话,我更倾向于使用它。我会告诉你结果的,谢谢。 - user4319995
这个解决方案对我来说适用于proto3和AutoMapper 6.2.2。 - Peter Wishart

0
如果您知道模型中的哪个成员是protobuf的重复字段,您可以指定映射目标值,而不是重复字段本身。这样可以避免protobuf重复字段没有公共“set”定义所带来的麻烦。
CreateMap<Model, ProtoModel>().ForMember(dest => dest.MyRepeatedCollection, opt => opt.UseDestinationValue());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接