はじめに
今回はprotobuf-net
というライブラリを利用して.NET上でprotocol buffers
を扱う方法を紹介したいと思います。
概要
protobuf-net
はprotocol buffers
のシリアライザーライブラリです。Google製ライブラリとしてGoogle.Protobuf
が挙げられますが、Unityで扱いづらいとの噂を聞いたことがあります(実際に試したわけではありません)。また後でここらへんを別記事にまとめようかなと思います。
protobuf-net is a contract based serializer for .NET code, that happens to write data in the "protocol buffers" serialization format engineered by Google. The API, however, is very different to Google's, and follows typical .NET patterns (it is broadly comparable, in usage, to XmlSerializer, DataContractSerializer, etc). It should work for most .NET languages that write standard types and can use attributes.
// DeepL翻訳
protobuf-netは、.NETコード用のコントラクトベースのシリアライザーで、Googleによって設計された「プロトコル・バッファ」シリアライゼーション・フォーマットでデータを書き込む。しかし、APIはGoogleのものとは大きく異なっており、典型的な.NETのパターンに従っている(XmlSerializerやDataContractSerializerなどと大まかな使い方は同じである)。標準的な型を記述し、属性を使用できるほとんどの.NET言語で動作するはずです。
GitHub - protobuf-net/protobuf-net: Protocol Buffers library for idiomatic .NET
またProtocol Buffers
の原理が知りたい方は以下を参照してみてください。
developers.google.com
サポートされているバージョン
- .NET 6.0+ (.NET 5 etc will use .NET Standard 2.1)
- .NET Standard 2.0, 2.1
- .NET Framework 4.6.2+
GitHub - protobuf-net/protobuf-net: Protocol Buffers library for idiomatic .NET
環境
- Rider 2023.1.3
- Console Application
- .net7.0
- C#11
インストール方法
Rider上のエクスプローラーから.csproj
を右クリックし、NuGetパッケージの管理
を選択します。
あとはprotobuf-net
と検索して右上の+
ボタンを押せばインストール完了です。
Riderプラグインの導入
JetBrains
製のProtocol Buffers
プラグインがあるので、これを導入すると便利です。proto2
とproto3
に対応しています。
Provides editor support for Protocol Buffers files.
導入方法は設定画面を開き、プラグイン > Protocol Buffers > インストール
からインストールを行なってください。
使い方
まずは.proto
を利用せずに、素朴な実装から使い方を見ていきます。具体的に以下の操作を行いました。
- シリアライズ・デシリアライズ対象の
class
に対して[ProtoContract]
をつけ、メンバーに対して[ProtoMember
を付与 ProtoBuf.Serializer.Serialize
を利用してシリアライズProtoBuf.Serializer.Deserialize
を利用してデシリアライズ
using ProtoBuf; // ------------------------------ // Decorate your classes // ------------------------------ // シリアライズ・デシリアライズ対象に[ProtoContract]をつける [ProtoContract] public class Person { // [ProtoMember]で一意のtagをつけていく [ProtoMember(1)] public int Id { get; set; } [ProtoMember(2)] public string Name { get; set; } [ProtoMember(3)] public Address Address { get; set; } } [ProtoContract] public class Address { [ProtoMember(1)] public string Line1 { get; set; } [ProtoMember(2)] public string Line2 { get; set; } } // ------------------------------ // Serialize・Deserialize your data // ------------------------------ internal class Program { public static void Main() { var person = new Person { Id = 12345, Name = "Hanachiru", Address = new Address { Line1 = "Line 1", Line2 = "Line 2" } }; // Serialize using (var file = File.Create("person.bin")) { // 実際に書き込まれるデータ(バイナリ) : 08 B9 60 12 09 48 61 6E 61 63 68 69 72 75 1A 10 0A 06 4C 69 6E 65 20 31 12 06 4C 69 6E 65 20 32 Serializer.Serialize(file, person); } // Deserialize Person newPerson; using (var file = File.OpenRead("person.bin")) { newPerson = Serializer.Deserialize<Person>(file); // 12345 Console.WriteLine(newPerson.Id); // Hanachiru Console.WriteLine(newPerson.Name); // Line 1 Console.WriteLine(newPerson.Address.Line1); // Line 2 Console.WriteLine(newPerson.Address.Line2); } } }
実際に触ってみれば結構シンプルですね。覚えることは[ProtoContract]
と[ProtoMember(1)]
で一意のtag
をつけるだけです。
.protoを利用する
.proto
ファイルを利用することで、上記の[ProtoContract]
が付与されているクラスを自動生成できます。記法はProtobugの公式ドキュメント or MSの公式ドキュメント あたりを参照すると良いでしょう。(特にMSの公式Docがオススメ)
protobuf.dev
learn.microsoft.com
せっかくRiderにプラグインを入れたので、Rider上で以下のファイルを作成しました。
// sample.proto syntax = "proto3"; option csharp_namespace = "Sample.Messages"; message Person { // Protobugスタイルガイドではフィールド名にunderscore_separated_namesを利用することが推奨 // .NET ツールでは自動で UnderScoreSeparatedNames のように変換してくれます int32 id = 1; string name = 2; Address address = 3; } message Address { string line1 = 1; string line2 = 2; }
.proto
からコード生成する方法は複数ありますが、一番楽なのは以下のサイトを利用することでしょう。(GitHubのReadmeにこのやり方が記載されていた)
protogen.marcgravell.com