gRPC响应类型问题

问题描述

我有一个gRPC服务DeviceCommWeb,该文件在.proto文件中具有以下rpc:

// NOTE: This is part of the .proto file

service DeviceCommWeb {
  rpc GetConnectedDevices(GetConnectedDevicesRequest) returns (stream GetConnectedDevicesResponse);
}

GetConnectedDevicesRequest消息:

// NOTE: This is part of the .proto file

message GetConnectedMessageRequest {
  enum DeviceType {
    USB = 0;
    HDMI = 1;
    displayPort = 2;
  }

  DeviceType deviceType = 1;
  string pdiuid = 2;
}

GetConnectedDevicesResponse消息:

// NOTE: This is part of the .proto file

message GetConnectedDevicesResponse {
  repeated DeviceComm devices = 1;
}

在服务中,我实现了GetConnectedDevices

public override async Task GetConnectedDevices(GetConnectedDevicesRequest,IServerStreamWriter<GetConnectedDevicesResponse> repsonseStream,ServerCallContext context)
{
  await responseStream.WriteAsync(ListConnectedDevices((DeviceType)request.DeviceType,Guid.Parse(request.uid)));
}

ListConnectedDevices方法

private GetConnectedDevicesResponse ListConnectedDevices(DeviceType deviceType,Guid uid)
{
  var connectedDevices = DeviceCommMoq.ConnectedDevices() // This is just a Moq. Returns a List<DeviceComm> of DeviceComm objects.

  var result = new GetCOnnectedDevicesResponse();

  foreach (DeviceComm device in connectedDevices)
  {
    // This is where I'm confused. How do I build the GetConnectedDevicesResponse?
  }
}

目标是获取DeviceCommMoq.ConnectedDevices()中已连接设备的列表,并将其作为GetConnectedDevicesResponse(或其中的一部分)返回。我不确定该怎么做,而我尝试的一切都会给我错误

Cannot implicitly convert type 'DeviceComm' to 'GetConnectedDevicesResponse'

我在做什么错?我觉得这里有一种更好的方法来达到最终目标。

解决方法

使用WriteAsync()意味着您必须读取特定的数据。

首先,致电using var response = yourGrpcClient.GetConnectedDevices()以获得ResponseStream。然后读取数据:

await foreach (var data in response.ResponseStream.ReadAllAsync())
{
   //Do Stuff
}

另外,如果您正在使用流,请WriteAsync() foreach循环中的每个元素。

已编辑

解决方案中有很多错误。让我们从.proto文件开始。响应包含多个DeviceComm元素。这是错误的,因为您正在使用流作为响应,这意味着GetConnectedDevicesResponse类型的流元素,因此您应该重新定义它。将repeated DeviceComm devices = 1;替换为DeviceComm属性。

在这种更改GetConnectedDevices之后,像这样:

public override async Task GetConnectedDevices(GetConnectedDevicesRequest,IServerStreamWriter<GetConnectedDevicesResponse> repsonseStream,ServerCallContext context)
{
  var connectedDevices = deDeviceCommMoq.ConnectedDevices();
  foreach(var device in connectedDevices)
  {
    await responseStream.WriteAsync(new GetConnectedDevicesResponse() { *Initialize properties from device object* });
  }
}

然后,您可以使用客户端示例。