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<YourType>(stream);

这里也有一个重载方法。

你可以传递一个Google.Protobuf.CodedOutputStream来替代System.IO.Stream

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

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

YourType model = Message.DeserializeFromBytes<YourType>(bytes);

字段定义

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

默认实现是GeneralMessageFieldProvider.Intance类。

它只会映射可读写的属性到消息字段。

你可以创建自己的IMessageFieldProvider去映射消息字段。

然后通过设置静态属性Message<T>.FieldProvider为自定义的IMessageFieldProvider

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

字段排序

给属性添加System.Runtime.Serialization.DataMemberAttribute特性然后设置Order属性。

不然将根据属性名称进行排序。

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

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

非空构造函数

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

获取Protobuf包装器

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

SimplyModel model;
Message<SimplyModel> message = model;

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

高级

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

C#类型 Protobuf类型 消息结构
bool(?) bool Varint
sbyte(?) int32 Varint
byte(?) int32 Varint
short(?) int32 Varint
ushort(?) int32 Varint
int(?) int32 Varint
long(?) int64 Varint
uint(?) uint32 Varint
ulong(?) uint64 Varint
float(?) float Varint
double(?) double Varint
string string Length-delimited
byte[] ByteString Length-delimited
Guid(?) ByteString Length-delimited
DateTime(?) google.protobuf.Timestamp Length-delimited
DateTimeOffset(?) google.protobuf.Timestamp Length-delimited
TimeSpan(?) google.protobuf.Duration Length-delimited
IMessage Length-delimited
T[] RepeatedField<T> Length-delimited
ICollection<T> RepeatedField<T> Length-delimited
Collection<T> RepeatedField<T> Length-delimited
IList<T> RepeatedField<T> Length-delimited
List<T> RepeatedField<T> Length-delimited
IDictionary<TKey, TValue> MapField<TKey, TValue> Length-delimited
Dictionary<TKey, TValue> MapField<TKey, TValue> Length-delimited
  • (?) 意思是可以为Nullable<>可空类型。
  • 可以直接使用继承了Google.Protobuf.IMessage的Protobuf对象作为属性类型。
  • 所有RepeatedFieldMapField对象不能包含null值。
  • 支持bytesbyteshortushort作为属性类型。

    它们将作为int类型进行序列化。

    如果从其它第三方来源数据进行反序列化,int可能会丢失数据。

如何工作

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

我们定义了一个抽象类Wodsoft.Protobuf.Message

然后定义抽象保护方法ReadWriteCalculateSize

显式实现这些接口并调用这些方法。

然后定义泛型抽象类Wodsoft.Protobuf.Message<T>

这里有一个属性可以直接获取到原始类型值。然后我们实现了一些隐式转换操作。

public T Source { get; }

最后,为需要序列化的类型动态创建继承了Message<T>的类。

通过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许可证。

.NET Protobuf包装器库的更多相关文章

  1. java基础类型、包装器

    char a = 'h';  //类包装器 Character aobj = a ;//自动装箱 byte b = 6; Byte bobj = b; short s = 234; Short sob ...

  2. C++11多态函数对象包装器

    [C++11多态函数对象包装器] 针对函数对象的多态包装器(又称多态函数对象包装器)在语义和语法上和函数指针相似,但不像函数指针那么狭隘.只要能被调用,且其参数能与包装器兼容的都能以多态函数对象包装器 ...

  3. ACE的包装器

    ACE大量运用包装器模式,以期改变面向过程的系统API可视性以及错误处理较难的情况 包装器在若干场合能极大简化代码量,甚至是编码过程 比如ACE_Thread_Mutex 对象创建会自动初始化,很开心 ...

  4. Java中基本数据类型和包装器类型的关系

    在程序设计中经常用到一系列的数据类型,在Java中也一样包含八中数据类型,这八种数据类型又各自对应一种包装器类型.如下表: 基本类型 包装器类型 boolean Boolean char Charac ...

  5. Java 装箱、拆箱 包装器

    先说java的基本数据类型.java基本数据类型:byte.short.int.long.float.double.char.boolean 基本数据类型的自动装箱(autoboxing).拆箱(un ...

  6. 翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化

    翻译:探索GLSL-用几何着色器(着色器库)实现法线可视化 翻译自: Exploring GLSL – Normal Visualizer with Geometry Shaders (Shader ...

  7. 【Head First Servlets and JSP】笔记 28: 过滤器与包装器

    1.过滤器的执行顺序: <url-pattern> 为第一梯队, <servlet-name> 为第二梯队,梯队内的执行顺序和 DD 里的声明顺序相同. When the co ...

  8. java基本类型和包装器类

    java是一种面向对象语言,java中的类把方法与数据连接在一起,并构成了自包含式的处理单元.但在java中不能定义基本类型(primitive type),为了能将基本类型视为对象来处理,并能连接相 ...

  9. 【Keras案例学习】 sklearn包装器使用示范(mnist_sklearn_wrapper)

    import numpy as np from keras.datasets import mnist from keras.models import Sequential from keras.l ...

随机推荐

  1. Visaul Studio Code中提示 vue:无法加载vue.ps1,未对vue.ps1进行数字签名

    Visaul Studio Code错误提示 错误如图: 解决办法 首先以管理员身份打开windows PowShell终端. 输入下面命令,如提示选择Y即可. get-help set-execut ...

  2. Windows10通过WSL编译jdk12

    Windows使用WSL编译OpenJDK 安装Ubuntu以及配置国内镜像 首选确保windows10已经安装了ubuntu 更换ubuntu20.04国内镜像,这里我选择的是阿里云镜像 sudo ...

  3. Django+Nginx+Uwsgi(全网最全步骤工作原理流程与部署历程)

    一.必要前提 1.1 准备知识 django 一个基于python的开源web框架,请确保自己熟悉它的框架目录结构. uWSGI 一个基于自有的uwsgi协议.wsgi协议和http服务协议的web网 ...

  4. Python代码阅读(第11篇):展开嵌套列表

    Python 代码阅读合集介绍:为什么不推荐Python初学者直接看项目源码 本篇阅读的代码实现了展开嵌套列表的功能,将一个嵌套的list展开成一个一维list(不改变原有列表的顺序). 本篇阅读的代 ...

  5. 使用 WPF + Chrome 内核实现 在线客服系统 的复合客服端程序

    本系列文章详细介绍使用 .net core 和 WPF 开发 升讯威在线客服与营销系统 的过程.本产品已经成熟稳定并投入商用. 免费使用 & 私有化部署免费下载:https://docs.sh ...

  6. Dapr + .NET Core实战(十一)单机Dapr集群负载均衡

    如何单机部署Dapr集群 第十篇讲过了K8S集群下如何使用Dapr运行程序,但是很多人一直在问如何单机下进行Dapr的负载,这节课我们来聊聊如何单机进行Dapr的负载. 首先要说的是单机下,通过 da ...

  7. 新版发布|ShardingSphere 5.0.0-beta 来了!

    Apache ShardingSphere 5.0.0-beta 版在经过长达半年的筹备后,终于将在近期正式 Release! 本文将带领大家一同预览新版本即将带来哪些重大亮点功能. 作者介绍 潘娟 ...

  8. Java秘诀!零基础怎样快速学习Java?

    对于零基础想学Java的朋友,其实一开始最应该做的就是定好学习目标和端正学习态度,切记不要三天打鱼两天晒网! 首先你是零基础,现在急需把Java学好,在保证学习质量的同时,用最短的时间学好Java应该 ...

  9. FastAPI 学习之路(十)请求体的字段

    系列文章: FastAPI 学习之路(一)fastapi--高性能web开发框架 FastAPI 学习之路(二) FastAPI 学习之路(三) FastAPI 学习之路(四) FastAPI 学习之 ...

  10. 解决git clone慢问题

    解决git clone慢 关于Git克隆或是上传代码龟速的问题真是让人很恼火,这里对于网上的两种解决方案进行摘录. 利用码云克隆github项目 亲测有效 进入码云,新建一个仓库: 在创建的最后选择导 ...