繁体   English   中英

在 gRPC/proto3 中设置 oneof 请求的更有效方法

[英]More efficient way to set a oneof request in gRPC/proto3

在 PHP 客户端和 Python 服务器上具有此 proto3 模式:

service GetAnimalData{
    rpc GetData (AnimalRequest) returns (AnimalData) {}
}

message AnimalRequest {
    OneOfAnimal TypeAnimal = 1;
}

message AnimalData {
    repeated int32 data = 1;
}

message OneOfAnimal {
    oneof animal_oneof {
        CAT cat = 1;
        DOG dog = 2;
    }
}

message CAT{
    int32 p = 1;
    int32 d = 2;
    int32 q = 3;
}

message DOG{
    int32 p = 1;
    int32 d = 2;
    int32 q = 3;
    int32 p2 = 4;
    int32 d2 = 5;
    int32 q2 = 6;
}

为了设置来自 PHP 客户端的请求,我需要执行以下操作:

  1. 创建一个新的CAT
  2. OneOfAnimal设置为CAT
  3. AnimalRequest.TypeAnimal设置为OneOfAnimal

是否有 proto3 的架构,我可以直接将CATDOG object 设置为我的AnimalRequest.TypeAnimal

笼统; 不,不是。

在某些非常具体的情况下,答案是“是” - 例如,protobuf-net(.NET 中的“代码优先”protobuf 实现)恰好以这种方式实现 inheritance,因此您可以使用:

[ProtoContract]
public class AnimalRequest {
    [ProtoMember(1)] public Animal Animal {get;set;}
}

[ProtoContract]
[ProtoInclude(1, typeof(Cat))]
[ProtoInclude(2, typeof(Dog))]
class Animal {} // acts identically to your OneOfAnimal message type

[ProtoContract]
class Cat {
    [ProtoMember(1)] public int P {get;set;}
    [ProtoMember(2)] public int D {get;set;}
    [ProtoMember(3)] public int Q {get;set;}
}

[ProtoContract]
class Dog {
    [ProtoMember(1)] public int P {get;set;}
    [ProtoMember(2)] public int D {get;set;}
    [ProtoMember(3)] public int Q {get;set;}
    [ProtoMember(4)] public int P2 {get;set;}
    [ProtoMember(5)] public int D2 {get;set;}
    [ProtoMember(6)] public int Q2 {get;set;}
}

然后你使用:

var result = svc.GetData(
    new AnimalRequest { Animal = new Dog { P = 42, ... Q2 = 19 } }
);

它会以完全相同的方式工作——发送相同的字节; 本质上,protobuf-net 将 inheritance 视为oneof (在类型层次结构中的每个级别)。

但是:因为.proto旨在以非常通用的“最小公分母”方式工作,所以 .proto 本身没有 inheritance 的概念.proto所以:你不能从.proto或谷歌库中做到这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM