如何在 protobuf-net.grpc 的消息中使用 IAsyncEnumerable?

Sos*_*der 6 c# protobuf-net grpc

所以,最近我学习了如何在 的帮助下使用 protobuf-net.grpc 进行流式传输IAsyncEnumerable<T>。这一切都运行得很好,但我现在面临着一些问题。

对于我的一些调用,我想使用一些元数据以及流作为参数进行调用。

例如:

[OperationContract]
Task<bool> UploadPicture(ProfilePictureQuery query);
Run Code Online (Sandbox Code Playgroud)

带有以下签名:

[ProtoContract]
public class ProfilePictureQuery
{
    [ProtoMember(1)]
    public IAsyncEnumerable<byte[]> RawDataStream { get; set; }

    [ProtoMember(2)]
    public string FileExtension { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

但是,当尝试调用它时,我遇到了类似的异常'Status(StatusCode=Unimplemented, Detail="Method is unimplemented.")。我知道状态响应有点神秘,所以我发现这实际上只是参数的问题。

那我该怎么做呢?

我还尝试使用以下签名来做到这一点:

[OperationContract]
Task<bool> UploadPicture(IAsyncEnumerable<byte[]> rawDataStream, string fileExtension);
Run Code Online (Sandbox Code Playgroud)

具有相同的结果,因为我显然只允许提供单个参数(符合一个消息参数和一个响应输出的 grpc 定义)。

Sooo,那我该怎么做呢?

Mar*_*ell 6

这里有两个独立的概念:

  • gRPC 允许通过消息流IAsyncEnumerable<T>(而不是Task<T>单个消息)
  • 但是,每条单独的消息必须完整且独立;编组器(每消息序列化器)仅是同步的

因此:您可以用作IAsyncEnunerable<T>服务方法的参数或返回,但不能用作消息上的字段。

如果您需要提供流和附加元数据,则存在以下几个选项:

  • 使用http标头(viaCallContext作为第二个参数)
  • 有两个服务调用 - 一个启动事物并获取元数据,一个返回流
  • 有一个消息中包含一些可选字段的流,并且仅填充第一条或最后一条消息中的可选字段