如何在protobuf-net代码优先gRPC中使用Google.Protobuf.WellknownTypes.Any
问题根源说明
你当前报错是因为混用了两个不同Protobuf库的类型:Google.Protobuf.WellknownTypes.Any是Google官方Protobuf库的类型,其Pack方法仅支持该库生成的、实现了Google.Protobuf.IMessage接口的类,而你用protobuf-net代码优先定义的[ProtoContract]类默认不会实现该接口,因此触发报错。
问题1:protobuf-net中Any类型的正确使用方式
protobuf-net内置了独立的Any类型实现,完全适配代码优先的使用模式,无需额外实现接口,用法如下:
- 将
MyMessage中Payload的类型替换为ProtoBuf.WellKnownTypes.Any(注意命名空间是protobuf-net的,不是Google官方库的) - 打包调用
ProtoBuf.WellKnownTypes.Any.CreateFrom(实例)方法 - 解包调用
Any.TryUnpack<T>(out T result)方法即可
示例代码:
// 调整后的MyMessage定义 [ProtoContract] public class MyMessage { [ProtoMember(1)] public int HeaderValue1 { get; set; } [ProtoMember(2)] public string HeaderValue2 { get; set; } [ProtoMember(3)] public ProtoBuf.WellKnownTypes.Any Payload { get; set; } } // 打包逻辑 Payload2 payload = new Payload2 { Data1 = "abc", Data2 = "def" }; MyMessage msg = new MyMessage { HeaderValue1 = 123, HeaderValue2 = "iAmHeaderValue2", Payload = ProtoBuf.WellKnownTypes.Any.CreateFrom(payload) }; // 解包逻辑 if (msg.Payload.TryUnpack<Payload2>(out var payload2)) { // 处理payload2 }
问题2:兼容Google.Protobuf.WellknownTypes.Any的简单方案
两个库的Any类型底层结构完全一致(都包含type_url和value两个字段),无需让你的类实现IMessage,手动序列化构造即可兼容:
using var ms = new MemoryStream(); // 用protobuf-net序列化你的自定义类 Serializer.Serialize(ms, payload); var googleAny = new Google.Protobuf.WellKnownTypes.Any { // TypeUrl按照官方规则赋值,也可以自定义规则只要收发两端一致即可 TypeUrl = $"type.googleapis.com/{typeof(Payload2).FullName}", Value = Google.Protobuf.ByteString.CopyFrom(ms.ToArray()) };
该方案生成的Any实例和官方库Pack方法生成的实例完全等价,跨语言、跨库交互都能正常识别。
问题3:是否必须实现Google.Protobuf.IMessage接口
不需要。
- 如果是纯protobuf-net技术栈的场景,直接用protobuf-net内置的Any类型即可,完全不需要涉及
Google.Protobuf.IMessage接口 - 如果需要和Google官方Protobuf库交互,用上述手动构造的方案即可,也不需要实现该接口
- 只有当你直接调用Google官方库的
Any.Pack方法时,才要求入参实现该接口,该场景完全可以用替代方案避开。
内容的提问来源于stack exchange,提问作者monty
相关产品推荐
相关产品推荐

