资讯专栏INFORMATION COLUMN

.NET Protobuf包装器库

Carl / 2422人阅读

摘要:不然将根据属性名称进行排序。获取包装器获取包装器我们可以直接转换模型对象为。所有与对象不能包含值。它们将作为类型进行序列化。我们定义了一个抽象类。使用会获得最佳性能。许可证许可证库使用许可证。

Wodsoft Protobuf Wrapper

内容

关于

这是一个可以帮助你不需要.proto文件就能够使用Protobuf序列化的一个库。

通常.proto文件会创建继承IMessage接口的模型,Protobuf使用这些模型来进行序列化。

有时候我们已经在自己的.NET项目里创建了一些模型,但我们需要使用Protobuf对这些模型进行序列化。
这时候这个库就能帮助你使用Protobuf对已存在的模型进行序列化。

Github地址:Wodsoft.Protobuf.Wrapper

需求

Wodsoft.Protobuf.Wrapper需要NETStandard 2.0或以上。

这个库需要工作在允许动态代码编译的平台。所以IOS不支持

安装

在NuGet上获取Wodsoft.Protobuf.Wrapper.

dotnet add package Wodsoft.Protobuf.Wrapper

用法

序列化

可以使用Wodsoft.Protobuf.Message类中的静态方法Serialize
你需要一个System.IO.Stream来存储序列化后的数据。

YourModel model = new ();MemoryStream stream = new MemoryStream();Message.Serialize(stream, model);

这里也有一个重载方法。
你可以传递一个Google.Protobuf.CodedInputStream来替代System.IO.Stream

YourModel model = new ();CodedInputStream input = ...;Message.Serialize(input, model);

或者你想直接拿到序列化后的字节数组。

YourModel model = new ();var bytes = Message.SerializeToBytes(model);

反序列化

你可以使用Wodsoft.Protobuf.Message类中的静态方法Deserialize
你需要传递包含需要反序列化数据的System.IO.Stream
它将返回你的泛型对象T

Stream stream = ...;YourType model = Message.Deserialize(stream);

这里也有一个重载方法。
你可以传递一个Google.Protobuf.CodedOutputStream来替代System.IO.Stream

CodedOutputStream output = ...;YourType model = Message.Deserialize(output);

或者你想直接从字节数组进行反序列化。

YourType model = Message.DeserializeFromBytes(bytes);

字段定义

IMessageFieldProvider.GetFields(Type type)会返回从对象映射而来的消息字段。

默认实现是GeneralMessageFieldProvider.Intance类。
它只会映射可读写的属性到消息字段。

你可以创建自己的IMessageFieldProvider去映射消息字段。
然后通过设置静态属性Message.FieldProvider为自定义的IMessageFieldProvider

你需要为每个需要自定义消息字段的类型设置IMessageFieldProvider

字段排序

给属性添加System.Runtime.Serialization.DataMemberAttribute特性然后设置Order属性。
不然将根据属性名称进行排序。

⚠️ 如果有任何一个属性使用了DataMemberAttribute特性,将只会序列化拥有DataMemberAttribute特性的属性。

⚠️ 如果全部没有使用DataMemberAttribute特性,服务如果因为部署问题使用了不同版本的模型,反序列化时可能因为字段排序问题存在错误。

非空构造函数

通过调用静态方法MessageBuilder.SetTypeInitializer(Func initializer)来设置对象初始化委托。

获取Protobuf包装器

我们可以直接转换模型对象为Message<>

SimplyModel model;Message message = model;

然后这个message可以直接被Protobuf序列化。

高级

支持的属性类型与Protobuf类型的关系

C#类型Protobuf类型消息结构
bool(?)boolVarint
sbyte(?)int32Varint
byte(?)int32Varint
short(?)int32Varint
ushort(?)int32Varint
int(?)int32Varint
long(?)int64Varint
uint(?)uint32Varint
ulong(?)uint64Varint
float(?)floatVarint
double(?)doubleVarint
stringstringLength-delimited
byte[]ByteStringLength-delimited
Guid(?)ByteStringLength-delimited
DateTime(?)google.protobuf.TimestampLength-delimited
DateTimeOffset(?)google.protobuf.TimestampLength-delimited
TimeSpan(?)google.protobuf.DurationLength-delimited
IMessageLength-delimited
T[]RepeatedFieldLength-delimited
ICollectionRepeatedFieldLength-delimited
CollectionRepeatedFieldLength-delimited
IListRepeatedFieldLength-delimited
ListRepeatedFieldLength-delimited
IDictionaryMapFieldLength-delimited
DictionaryMapFieldLength-delimited
  • (?) 意思是可以为Nullable<>可空类型。
  • 可以直接使用继承了Google.Protobuf.IMessage的Protobuf对象作为属性类型。
  • 所有RepeatedFieldMapField对象不能包含null值。
  • 支持bytesbyteshortushort作为属性类型。
    它们将作为int类型进行序列化。
    如果从其它第三方来源数据进行反序列化,int可能会丢失数据。

如何工作

首先,Protobuf通过Google.Protobuf.IMessageGoogle.Protobuf.IBufferMessage接口进行序列化工作。

我们定义了一个抽象类Wodsoft.Protobuf.Message
然后定义抽象保护方法ReadWriteCalculateSize
显式实现这些接口并调用这些方法。

然后定义泛型抽象类Wodsoft.Protobuf.Message
这里有一个属性可以直接获取到原始类型值。然后我们实现了一些隐式转换操作。

public T Source { get; }

最后,为需要序列化的类型动态创建继承了Message的类。
通过Emit动态创建代码实现ReadWriteCalculateSize方法。

性能

  • 建议使用 RepeatedField<>IList<>ICollection<>作为集合属性的类型。
    使用RepeatedField<>会获得最佳性能(因为不需要额外类型转换)。
  • 使用IList<>ICollection<>在序列化时会转换为RepeatedField<>
  • 使用List<>Collection<>在序列化时会转换为RepeatedField<>
    并且在反序列化时会转换回List<>Collection<>(上一个会直接返回RepeatedField<>)。
  • 推荐使用 MapField<,>IDictionary<,>作为字典属性的类型。
    使用MapField<,>会获得最佳性能
  • 使用IDictionary<,>在序列化时会转换为MapField<,>
  • 使用Dictionary<,>在序列化时会转换为MapField<,>
    并且在反序列化时会转换回Dictionary<,>(上一个会直接返回MapField<,>)。

许可证

库使用MIT许可证。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/123653.html

相关文章

  • C#中使用protobuf-net进行序列化

    摘要:通过类库提供的和分别执行序列化和反序列化,而不用依赖任何生成的代码。只针对平台的话,不需要文件就可以应用序列化协议。前一篇文章我们看到使用Google.Protobuf有诸多不便(参考《如何在C#中使用Google.Protobuf工具》),这次我们来看看另一个工具的使用体验。相关资料、链接:github项目:https://github.com/protobuf-net/protobuf-...

    不知名网友 评论0 收藏0
  • Google Protobuf 编解码

    摘要:优点在谷歌内部长期使用产品成熟度高跨语言支持多种语言包括和编码后的消息更小更加有利于存储和传输编解码的性能非常高支持不同协议版本的前向兼容支持定义可选和必选字段的入门是一个灵活高效结构化的数据序列化框架相比与等传统的序列化工具它更小更快更简 Google Protobuf 优点: 在谷歌内部长期使用, 产品成熟度高. 跨语言、支持多种语言, 包括 C++、Java 和 Python....

    Eric 评论0 收藏0
  • Python爬虫120例之案例58,手机APP爬虫,“武器库”的准备and皮皮虾APP的测试

    摘要:在爬虫的编写过程中使用最多的是,它表示查看请求和响应的数据内容。后续在打开刚才加载的软件,例如本次案例打开的是皮皮虾,开启,成功捕获到如下请求,这个地方就是最终的接口了。复制接口地址,在本地浏览器打开,得到皮皮虾的视频评论数据。 ...

    roundstones 评论0 收藏0
  • Docker 技术与 Coding.net 技术架构的变迁

    摘要:采用微服务架构设计的原因很简单解放生产力。运行时服务缺少标准,各类实现区别很大,调试困难程度不一,集成测试更是难上加难。小伙伴们更进一步的互相提供帮助集成测试及单元测试,极大的释放了团队生产力。 showImg(https://dn-coding-net-production-pp.qbox.me/e205ba4f-5db9-4719-bc00-cae9823c2d74.png); ...

    Sunxb 评论0 收藏0
  • 使用java google protobuf遇到一个的小坑

    摘要:公司使用来作为通讯格式,一个同事这样的写法文件格式使用的时候这时候拿到的是一个要是改成这样这时候拿到的是一个为什么会出现这种情况呢读了源码才知道是这样处理的这里发现只要才会进行包装,要不调用的是那么是什么时候变成不为呢继续看代码发现只要是调 公司使用protobuf来作为通讯格式,一个同事这样的写法proto文件格式: message PlayerFightQueue { op...

    tinysun1234 评论0 收藏0

发表评论

0条评论

Carl

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<