如何从消息类型的描述符Proto获取解析器?



在第一个 #region 中创建消息后,以下代码使用 Google.Protobuf 库在第二个 #region 中将消息的有线格式二进制转换为 json 字符串

static void Main(string[] args)
{
#region create example object and write it to a file in binary wire format
var john = new Person // defined in Addressbook.cs protoc-compiled from addressbook.proto
{
Id = 1234,
Name = "John Doe",
Email = "jdoe@example.com",
Phones = { new PhoneNumber { Number = "555-4321", Type = PhoneType.Home } }
};
var binaryFileName = "john";
using (var output = File.Create(binaryFileName))
{
john.WriteTo(output);
}
#endregion
#region convert wire format binary to json
using (var input = File.OpenRead(binaryFileName))
{
var message = Person.Descriptor.Parser.ParseFrom(input);
var json = new JsonFormatter(JsonFormatter.Settings.Default).Format(message);
Console.WriteLine(json);
}
#endregion
}

我想使用 protobuf-net 库重新创建此功能,通过 .proto 文件中的反射获取Descriptor,而不是从该 .proto 文件编译的源代码。

我得到了消息的描述符。如何从DescriptorProto获得等效MessageParser

static void Main(string[] args)
{
var binaryFileName = "john";
var set = new FileDescriptorSet();
set.Add("addressbook.proto", true, new StreamReader("addressbook.proto"));
set.Process();

var errors = set.GetErrors();
foreach (var error in errors)
{
Console.WriteLine(error);
}

foreach (var file in set.Files)
{
Console.WriteLine(file.Name);
foreach (var messageType in file.MessageTypes)
{
Console.WriteLine(messageType.Name);
}
}

var personType = set.Files.SelectMany(file => file.MessageTypes).FirstOrDefault(messageType => messageType.Name == "Person");
// personType.Parser. ???
}
>澄清/评论

我想你要问的是:给定一个仅在运行时通过解析的 .proto 知道的模式,我们如何反序列化数据 - 大概是一些仅限运行时的模型(我们不应该假设我们可以访问任何生成/匹配的类型(。

最终,我想在有线二进制格式之间转换为人类可读的文本,请参阅如何在运行时给定其 .proto 文件将二进制消息转换为人类可读格式(例如 json(?

如果有任何其他方法可以进行这种格式转换,我不一定需要任何模型来反序列化以及从哪个模型进行序列化/格式化到可读文本。这只是似乎最有可能实际工作的工作流程,至少从我在网上找到的工作流程来看。

问题在于,这种基于反射的 ProtoBuffers 处理所需的运行时功能在语言之间是不同的(甚至您指出的是一种语言的库(。可能的解决方案的丑陋程度很难估计,因为它总是来自非常详细的方面,例如需要编译的模式,需要调用protoc,无法从DescriptorProto获取解析器,在C#中没有可用的某些功能等。

这就是为什么我试图实施不同的解决方案,就像这个问题中的解决方案一样,看看那条特定的道路是否被堵住了,如果是的话,是被墙还是山挡住了。

我想你要问的是:给定一个仅在运行时通过解析的 .proto 知道的模式,我们如何反序列化数据 - 大概是一些仅限运行时的模型(我们不应该假设我们可以访问任何生成/匹配的类型(。

如果这是正确的,那么这是目前未在protobuf-net中实现的功能。您可以将数据作为Extensible子类读取,然后通过扩展 API 手动访问字段,但这将是困难、缓慢和丑陋的。另一种选择可能是在运行时在 C# 中生成匹配模型,编译并运行它 - 但这又是:复杂且不一定特别快(除非您可以缓存类型等(。还有一个阅读器 API,如果您想逐个字段地遍历 protobuf 流,并且对于每个字段:与您持有的架构进行比较,然后执行......有价值观的东西。

最终,我还没有完成发现工作来想象这个场景的可用和有用的API 是什么,更不用说实现它了。我愿意接受建议,但可能是关于 GitHub 问题。

最新更新