如何在gRPC代码优先服务中实现多态返回类型?
在gRPC代码优先服务中实现多态返回类型(BaseResponse不可修改场景)
由于你无法修改第三方库中的BaseResponse基类,无法直接通过[ProtoInclude]特性声明多态类型,可通过以下方式实现gRPC代码优先的多态返回:
1. 为派生类和请求类添加Protobuf序列化标记
首先确保所有需要序列化的类型被Protobuf识别,需引用protobuf-net和protobuf-net.Grpc NuGet包,然后添加对应特性:
[ProtoContract] public class HelloRequest { [ProtoMember(1)] public string Name { get; set; } } [ProtoContract] public class ResponseA : BaseResponse { [ProtoMember(1)] public string foo { get; set; } } [ProtoContract] public class ResponseB : BaseResponse { [ProtoMember(1)] public string bar { get; set; } }
2. 运行时注册派生类型到基类
在应用启动阶段(如Program.cs),通过RuntimeTypeModel将派生类型关联到BaseResponse,让Protobuf序列化器知晓多态关系:
RuntimeTypeModel.Default.Add(typeof(BaseResponse), true) .AddSubType(2, typeof(ResponseA)) .AddSubType(3, typeof(ResponseB));
注:子类型的序号(2、3)需唯一,且不能与基类成员的序列化序号冲突。
BaseResponse的hoo作为公共字段会被自动分配序号1,因此子类型从2开始编号即可。
3. 服务契约与实现保持原样
你的服务接口和实现无需修改,直接使用即可:
[ServiceContract] public interface IGreeterService { [OperationContract] BaseResponse SayHello(HelloRequest request, CallContext context = default); } public class GreeterService : IGreeterService { public BaseResponse SayHello(HelloRequest request, CallContext context = default) { if (request.Name == "Heelo") { return new ResponseA() { foo = "Hi", hoo = "Hey" }; } else return new ResponseB() { bar = "bye", hoo = "You" }; } }
4. 客户端同步配置
客户端必须执行相同的派生类型注册操作,否则无法正确反序列化多态响应:
RuntimeTypeModel.Default.Add(typeof(BaseResponse), true) .AddSubType(2, typeof(ResponseA)) .AddSubType(3, typeof(ResponseB));
内容的提问来源于stack exchange,提问作者sorosh_sabz
相关产品推荐
相关产品推荐

