Protocol Buffers (protobuf) is a language-neutral, platform-independent binary serialization format developed by Google. It offers superior performance over text-based formats like XML or JSON and is widely used in network communication, configuration storage, and cross-platform data exchange.
To generate C# classes from a .proto definition, you can use the protogen.exe tool provided by the protobuf-net library. Here’s a sample .proto file defining a request structure:
syntax = "proto2";
package hrv;
option java_package = "com.example.protobuf";
option java_outer_classname = "RequestProto";
message Request {
extensions 100 to max;
enum Type {
LOGIN = 0;
CHANGE_PASSWORD = 1;
START_SCALE = 2;
STOP_SCALE = 3;
DATA_PPG = 4;
DATA_EP = 5;
DATA_HRV = 6;
DATA_IBI = 7;
MARK_SCALE = 8;
RESOURCE_LIST = 9;
UPDATE_USER_INFO = 10;
GET_SCALE_LIST = 11;
GET_SCALE = 12;
}
required Type type = 1;
optional string timestamp = 2;
}
Run the following command in you're terminal to convert it into a C# class:
protogen.exe -i:Request.proto -o:Request.cs
You can also customize the output namespace and add using directives:
protogen.exe -i:Request.proto -o:Request.cs -ns:MyApp.Models -p:import=MyApp
This generates a strongly-typed C# class decorated with ProtoBuf attributes for serialization:
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// </auto-generated>
//------------------------------------------------------------------------------
namespace hrv
{
[global::System.Serializable, global::ProtoBuf.ProtoContract(Name = @"Request")]
public partial class Request : global::ProtoBuf.IExtensible
{
private Type _requestType;
[global::ProtoBuf.ProtoMember(1, IsRequired = true, Name = @"type", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)]
public Type requestType
{
get => _requestType;
set => _requestType = value;
}
private string _timestamp = "";
[global::ProtoBuf.ProtoMember(2, IsRequired = false, Name = @"timestamp", DataFormat = global::ProtoBuf.DataFormat.Default)]
[global::System.ComponentModel.DefaultValue("")]
public string timestamp
{
get => _timestamp;
set => _timestamp = value;
}
[global::ProtoBuf.ProtoContract(Name = @"Type")]
public enum Type
{
[global::ProtoBuf.ProtoEnum(Name = @"LOGIN", Value = 0)] LOGIN = 0,
[global::ProtoBuf.ProtoEnum(Name = @"CHANGE_PASSWORD", Value = 1)] CHANGE_PASSWORD = 1,
[global::ProtoBuf.ProtoEnum(Name = @"START_SCALE", Value = 2)] START_SCALE = 2,
[global::ProtoBuf.ProtoEnum(Name = @"STOP_SCALE", Value = 3)] STOP_SCALE = 3,
[global::ProtoBuf.ProtoEnum(Name = @"DATA_PPG", Value = 4)] DATA_PPG = 4,
[global::ProtoBuf.ProtoEnum(Name = @"DATA_EP", Value = 5)] DATA_EP = 5,
[global::ProtoBuf.ProtoEnum(Name = @"DATA_HRV", Value = 6)] DATA_HRV = 6,
[global::ProtoBuf.ProtoEnum(Name = @"DATA_IBI", Value = 7)] DATA_IBI = 7,
[global::ProtoBuf.ProtoEnum(Name = @"MARK_SCALE", Value = 8)] MARK_SCALE = 8,
[global::ProtoBuf.ProtoEnum(Name = @"RESOURCE_LIST", Value = 9)] RESOURCE_LIST = 9,
[global::ProtoBuf.ProtoEnum(Name = @"UPDATE_USER_INFO", Value = 10)] UPDATE_USER_INFO = 10,
[global::ProtoBuf.ProtoEnum(Name = @"GET_SCALE_LIST", Value = 11)] GET_SCALE_LIST = 11,
[global::ProtoBuf.ProtoEnum(Name = @"GET_SCALE", Value = 12)] GET_SCALE = 12
}
private global::ProtoBuf.IExtension extensionObject;
global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing)
=> global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing);
}
}
To automate generation for multiple files, use a Windows batch script:
@echo off
set PROTOGEN_PATH=ProtoGen\protogen.exe
%PROTOGEN_PATH% -i:Request.proto -o:OpenAPIModel\Request.cs
%PROTOGEN_PATH% -i:Response.proto -o:OpenAPIModel\Response.cs
%PROTOGEN_PATH% -i:UserInfo.proto -o:OpenAPIModel\UserInfo.cs
%PROTOGEN_PATH% -i:LoginReq.proto -o:OpenAPIModel\LoginReq.cs
%PROTOGEN_PATH% -i:LoginResp.proto -o:OpenAPIModel\LoginResp.cs
pause
Or recursively process all .proto files in a directory:
@echo off
set PROTOGEN_PATH=ProtoGen\protogen.exe
for %%f in (proto\*.proto) do (
%PROTOGEN_PATH% -i:"%%f" -o:"cs\%%~nf.cs"
)
pause