Более эффективный способ установки запроса oneof в gRPC / proto3 - PullRequest
1 голос
/ 17 июня 2020

Имея эту схему proto3 на клиенте PHP и Python сервере:

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, где я могу просто установить объект CAT или DOG напрямую как мой AnimalRequest.TypeAnimal

1 Ответ

1 голос
/ 17 июня 2020

В общих чертах; нет, не совсем.

В некоторых очень специфичных c случаях ответ будет «да» - например, protobuf- net (реализация protobuf «сначала код» in. NET) реализует наследование в точно таким образом, поэтому вы можете использовать:

[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 обрабатывает наследование как oneof (на каждом уровне иерархии типов).

Но: поскольку .proto предназначен для работы в очень общем c "наименьшем общем знаменателе "Кстати, .proto сам не имеет концепции наследования , поэтому: вы не можете сделать это из .proto или библиотек Google.

...