如何从消息类型的 DescriptorProto 中获取 Parser?
How to get a Parser from a DescriptorProto of a message type?
在第一个#region 中创建后,以下代码使用 Google.Protobuf library
在第二个#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 文件而不是从该 .proto 文件编译的源代码获取 Descriptor
来重新创建此功能。
我得到了消息的描述符。 我怎样才能从 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. ???
}
clarification/comments
I think what you're asking is: given a schema known only at runtime via a parsed .proto, how can we deserialize the data - presumably into some runtime-only model (we should not assume that we have access to any generated/matching types).
最后,我想将有线二进制格式转换为人类可读的文本,请参阅 How to convert a binary message to a human readable format (e.g. json) given its .proto file at runtime?
如果有任何其他方法可以进行这种格式转换,我不一定需要任何模型来反序列化和从中反序列化 serialization/formatting 到可读文本。 这只是看起来最有可能实际工作的工作流程,至少从我在网上找到的内容来看是这样。
问题在于,这种基于反射的 ProtoBuffers 处理所需的运行时功能在不同语言之间是不同的(甚至如您所指出的一种语言的库)。很难估计可能解决方案的丑陋程度,因为它总是来自非常详细的方面,例如需要编译模式,需要调用 protoc,无法从 DescriptorProto
获取解析器,在 C# 中没有可用的某些功能,等等
这就是为什么我要尝试实施不同的解决方案,例如这个问题中的解决方案,以查看该特定道路是否被阻挡,如果被阻挡,是否被墙或山所阻挡。
我认为您要问的是:给定一个仅在 运行 时间通过解析的 .proto 已知的模式,我们如何反序列化数据 - 大概是一些 运行 时间模型(我们不应该假设我们可以访问任何 generated/matching 类型)。
如果这是正确的,那么这是 protobuf-net 当前未实现的功能。您 可以 将数据作为 Extensible
子类读取,然后通过扩展 API 手动访问字段,但这会很困难、很慢而且很难看。另一种选择可能是在 运行 时间用 C# 生成匹配模型,编译它,然后 运行 它——但这又是:复杂而且不一定特别快(除非你可以缓存类型等) .还有一个 reader API,如果你想逐个字段地遍历一个 protobuf 流,并且对于每个:与你持有的模式进行比较,然后做......一些事情与价值观。
最终,我还没有完成发现工作来想象这种情况下可用和有用 API,更不用说实施了。我乐于接受建议,但可能是 GitHub 个问题。
在第一个#region 中创建后,以下代码使用 Google.Protobuf library
在第二个#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 文件而不是从该 .proto 文件编译的源代码获取 Descriptor
来重新创建此功能。
我得到了消息的描述符。 我怎样才能从 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. ???
}
clarification/comments
I think what you're asking is: given a schema known only at runtime via a parsed .proto, how can we deserialize the data - presumably into some runtime-only model (we should not assume that we have access to any generated/matching types).
最后,我想将有线二进制格式转换为人类可读的文本,请参阅 How to convert a binary message to a human readable format (e.g. json) given its .proto file at runtime?
如果有任何其他方法可以进行这种格式转换,我不一定需要任何模型来反序列化和从中反序列化 serialization/formatting 到可读文本。 这只是看起来最有可能实际工作的工作流程,至少从我在网上找到的内容来看是这样。
问题在于,这种基于反射的 ProtoBuffers 处理所需的运行时功能在不同语言之间是不同的(甚至如您所指出的一种语言的库)。很难估计可能解决方案的丑陋程度,因为它总是来自非常详细的方面,例如需要编译模式,需要调用 protoc,无法从 DescriptorProto
获取解析器,在 C# 中没有可用的某些功能,等等
这就是为什么我要尝试实施不同的解决方案,例如这个问题中的解决方案,以查看该特定道路是否被阻挡,如果被阻挡,是否被墙或山所阻挡。
我认为您要问的是:给定一个仅在 运行 时间通过解析的 .proto 已知的模式,我们如何反序列化数据 - 大概是一些 运行 时间模型(我们不应该假设我们可以访问任何 generated/matching 类型)。
如果这是正确的,那么这是 protobuf-net 当前未实现的功能。您 可以 将数据作为 Extensible
子类读取,然后通过扩展 API 手动访问字段,但这会很困难、很慢而且很难看。另一种选择可能是在 运行 时间用 C# 生成匹配模型,编译它,然后 运行 它——但这又是:复杂而且不一定特别快(除非你可以缓存类型等) .还有一个 reader API,如果你想逐个字段地遍历一个 protobuf 流,并且对于每个:与你持有的模式进行比较,然后做......一些事情与价值观。
最终,我还没有完成发现工作来想象这种情况下可用和有用 API,更不用说实施了。我乐于接受建议,但可能是 GitHub 个问题。