由于它不能直接使用C#对象,所以我们还需要创建一个*.proto
文件,布局和上面的C#类一致,加入了一个DemoClassArrayProto
方便后面测试:
syntax="proto3";option csharp_namespace="DemoClassProto";package DemoClassProto;message DemoClassArrayProto{repeated DemoClassProto DemoClass = 1;}message DemoClassProto{int32 P1=1;bool P2=2;string P3=3;double P4=4;int64 P5=5;repeated DemoSubClassProto Subs=6;}message DemoSubClassProto{int32 P1=1;bool P2=2;string P3=3;double P4=4;int64 P5=5;}
做完这一些后 , 还需要在项目文件中加入如下的配置 , 让Grpc.Tools
在编译时生成对应的C#类:
<ItemGroup><Protobuf Include="*.proto" GrpcServices="Server" /></ItemGroup>
然后Build当前项目的话就会在obj
目录生成C#类:
文章插图
文章插图
最后我们可以用下面的方法来实现序列化和反序列化,泛型类型
T
是需要继承IMessage<T>
从*.proto
生成的实体(用起来还是挺麻烦的):using Google.Protobuf;// Serialize[MethodImpl(MethodImplOptions.AggressiveInlining)]public static byte[] GoogleProtobufSerialize<T>(T origin) where T : IMessage<T>{return origin.ToByteArray();}// Deserialize[MethodImpl(MethodImplOptions.AggressiveInlining)]public DemoClassArrayProto GoogleProtobufDeserialize(byte[] bytes){return DemoClassArrayProto.Parser.ParseFrom(bytes);}
Protobuf.Net那么在.NET平台protobuf有没有更简单的使用方式呢?答案当然是有的,我们只需要依赖下面的Nuget包:<PackageReference Include="protobuf-net" Version="3.1.22" />
然后给我们需要进行序列化的C#类打上ProtoContract
特性,另外将所需要序列化的属性打上ProtoMember
特性,如下所示:[ProtoContract]public class DemoClass{[ProtoMember(1)] public int P1 { get; set; }[ProtoMember(2)] public bool P2 { get; set; }[ProtoMember(3)] public string P3 { get; set; } = null!;[ProtoMember(4)] public double P4 { get; set; }[ProtoMember(5)] public long P5 { get; set; }}
然后就可以直接使用框架提供的静态类进行序列化和反序列化,遗憾的是它没有提供直接返回byte[]
的方法,不得不使用一个MemoryStrem
:using ProtoBuf;// Serialize[MethodImpl(MethodImplOptions.AggressiveInlining)]public static void ProtoBufDotNet<T>(T origin, Stream stream){Serializer.Serialize(stream, origin);}// Deserializepublic T ProtobufDotNet(byte[] bytes){using var stream = new MemoryStream(bytes);return Serializer.Deserialize<T>(stream);}
MessagePack这里我们使用的是Yoshifumi Kawai实现的MessagePack-CSharp
,同样也是引入一个Nuget包:<PackageReference Include="MessagePack" Version="2.4.35" />
然后在类上只需要打一个MessagePackObject
的特性,然后在需要序列化的属性打上Key
特性:[MessagePackObject]public partial class DemoClass{[Key(0)] public int P1 { get; set; }[Key(1)] public bool P2 { get; set; }[Key(2)] public string P3 { get; set; } = null!;[Key(3)] public double P4 { get; set; }[Key(4)] public long P5 { get; set; }}
使用起来也非常简单,直接调用MessagePack
提供的静态类即可:using MessagePack;// Serialize[MethodImpl(MethodImplOptions.AggressiveInlining)]public static byte[] MessagePack<T>(T origin){return global::MessagePack.MessagePackSerializer.Serialize(origin);}// Deserializepublic T MessagePack<T>(byte[] bytes){return global::MessagePack.MessagePackSerializer.Deserialize<T>(bytes);}
另外它提供了Lz4算法的压缩程序,我们只需要配置Option,即可使用Lz4压缩,压缩有两种方式,Lz4Block
和Lz4BlockArray
,我们试试:public static readonly MessagePackSerializerOptions MpLz4BOptions =MessagePackSerializerOptions.Standard.WithCompression(MessagePackCompression.Lz4Block);// Serialize[MethodImpl(MethodImplOptions.AggressiveInlining)]public static byte[] MessagePackLz4Block<T>(T origin){return global::MessagePack.MessagePackSerializer.Serialize(origin, MpLz4BOptions);}// Deserializepublic T MessagePackLz4Block<T>(byte[] bytes){return global::MessagePack.MessagePackSerializer.Deserialize<T>(bytes, MpLz4BOptions);}
MemoryPack这里也是Yoshifumi Kawai大佬实现的MemoryPack
,同样也是引入一个Nuget包,不过需要注意的是,目前需要安装VS 2022 17.3以上版本和.NET7 SDK,因为MemoryPack
代码生成依赖了它:<PackageReference Include="MemoryPack" Version="1.4.4" />
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 华为云 MRS 基于 Apache Hudi 极致查询优化的探索实践
- 基于 .NET 7 的 QUIC 实现 Echo 服务
- 《ASP.NET Core技术内幕与项目实战》精简集-目录
- 上 学习ASP.NET Core Blazor编程系列十——路由
- 重新整理 .net core 实践篇 ———— linux上性能排查 [外篇]
- Sql Server性能排查和优化懒人攻略
- 在 .NET 7上使用 WASM 和 WASI
- 重新整理 .net core 实践篇 ———— linux上排查问题实用工具 [外篇]
- .NET 7 中 LINQ 的疯狂性能提升
- Vue3的新特性