Search code examples
c#grpc.net-core-3.1protobuf-3

The right way to send generic data types with protobuf3 in C#/.NET


I'm developing an application using a plugins architecture and I want to send objects between client and server without knowing the type of the object being sent.

Is there a way to send generic data type ?

According to Microsoft pages, the Any field could be an answer to this problem, instead of using a string and a custom serialization/deserialization implementation to send these objects. However, I didn't find the provided c# examples understandable. I tried to solve the problem this way:

ClassTest myClassTest = new ClassTest();
Any packToSend = Any.Pack(myClassTest);

return Task.FromResult(new UnknownTEST
{
   Pathm = hai
}); ;

But it seems that I need to implement the IMessage interface in my class and I don't know how to do this.

If anyone could provide a basic example to help me understand how to do this, that would be great.

Thanks !


Solution

  • You need to create protobuf messages which represent the data you're sending. You don't need to create your own classes as you did with your "ClassTest" class.

    Here's an example:

    point.proto:

    syntax = "proto3";
    option csharp_namespace = "MyProject.Namespace";
    
    message Point {
        int32 x = 1;
        int32 y = 2;
    }
    

    generic_dto_message.proto:

    syntax = "proto3";
    import "google/protobuf/any.proto";
    option csharp_namespace = "MyProject.Namespace";
    
    message GenericDtoMessage {
        google.protobuf.Any data = 1;
    }
    

    C# code:

    // packing
    var point = new Point
    {
        X = 1,
        Y = 22
    };
    var genericDtoMessage = new GenericDtoMessage();
    genericDtoMessage.Data = Any.Pack(point);
    
    
    // unpacking
    var unpackedData = genericDtoMessage.Data.Unpack<Point>();
    Console.WriteLine($"X: {unpackedData.X}{Environment.NewLine}Y: {unpackedData.Y}");
    Console.WriteLine($"Press any key to continue...");
    Console.ReadKey();
    

    In case you are using Grpc.Tools NuGet package to generate C# code for the above written .proto files, don't forget to add this ItemGroup section to your .csproj file:

    <ItemGroup>
      <Protobuf Include="point.proto" Link="point.proto" />
      <Protobuf Include="generic_dto_message.proto" Link="generic_dto_message.proto" />
    </ItemGroup>
    

    Hope it helps!