gRPC反向编译:从已编译.g.cs文件生成.proto定义
从gRPC的.g.cs文件反向生成.proto文件的方法
当然可以尝试反向推导生成.proto文件,但得先给你打个预防针:这个过程没法100%还原原始的.proto文件——因为编译成.g.cs时,一些注释、格式细节甚至部分可选的proto语法会被丢弃,但核心的服务接口定义、消息结构这些关键内容是完全可以恢复的。
下面是几种实用的方法:
1. 借助Protobuf反射API提取定义
这是最可靠的方法之一,利用Google.Protobuf的反射能力从编译后的类型中导出.proto内容:
首先,你需要把.g.cs文件编译成一个.NET类库(或者直接在现有项目中引用对应的类型),然后编写一段简单的代码来提取描述符:
using Google.Protobuf.Reflection; using System.IO; using System.Linq; // 替换成你的g.cs文件中定义的gRPC客户端或服务类型 var serviceType = typeof(YourGrpcServiceClient); var assembly = serviceType.Assembly; // 获取服务描述符 var serviceDescriptor = assembly.GetTypes() .Where(t => t.IsSubclassOf(typeof(Grpc.Core.ClientBase))) .Select(t => t.GetProperty("Descriptor")?.GetValue(null) as ServiceDescriptor) .FirstOrDefault(d => d != null); if (serviceDescriptor != null) { // 将描述符写入.proto文件 using var writer = new StringWriter(); serviceDescriptor.File.WriteTo(writer); File.WriteAllText("recovered_service.proto", writer.ToString()); // 如果还有其他关联的消息定义,也可以一并导出 foreach (var messageFile in serviceDescriptor.File.Dependencies) { using var msgWriter = new StringWriter(); messageFile.WriteTo(msgWriter); File.WriteAllText($"recovered_{messageFile.Name}", msgWriter.ToString()); } }
这种方法能准确提取服务的方法定义、消息的字段类型和编号,但原始的注释、自定义的protobuf选项(比如HTTP映射注解)可能会丢失。
2. 使用第三方反编译工具
如果不想写代码,也可以试试这些工具:
- protobuf-net.Reflection:和上面的思路类似,属于protobuf-net生态的工具,支持从.NET程序集中导出protobuf描述符并生成.proto文件。
- ILSpy 插件:把编译好的DLL用ILSpy打开,安装专门识别protobuf/gRPC结构的插件后,可以直接查看并导出对应的.proto内容。不过这个需要额外配置插件,适合不想写代码的场景。
注意事项
- 无法还原的内容:原始.proto中的注释、自定义选项(如
[(google.api.http)])、格式排版(换行、缩进)、部分被编译优化掉的废弃字段标记,这些大概率无法恢复。 - 版本兼容性:尽量使用和编译.g.cs时相同版本的gRPC/protobuf工具,避免版本不兼容导致的解析问题。
- 仅源码的情况:如果你只有.g.cs源码文件,没有编译后的程序集,先把它打包成一个临时的.NET类库项目并编译,再用上面的方法处理。
总的来说,虽然没法完美复刻原始.proto,但这些方法足够让你恢复核心的服务和消息定义,完全能满足重新编译、扩展服务的需求。
内容的提问来源于stack exchange,提问作者coryn
相关产品推荐
相关产品推荐

