【发布时间】:2011-02-14 19:09:07
【问题描述】:
我已经用 protobuf-net 序列化了一个对象列表。
理论上,.bin 文件可以包含数百万个对象。
假设对象属于包含以下内容的类:
public string EventName;
我必须进行查询并创建一个包含与查询匹配的对象的列表。 使用 LINQ 从序列化文件中提取匹配对象的正确方法是什么?
【问题讨论】:
标签: c# .net protobuf-net
我已经用 protobuf-net 序列化了一个对象列表。
理论上,.bin 文件可以包含数百万个对象。
假设对象属于包含以下内容的类:
public string EventName;
我必须进行查询并创建一个包含与查询匹配的对象的列表。 使用 LINQ 从序列化文件中提取匹配对象的正确方法是什么?
【问题讨论】:
标签: c# .net protobuf-net
protobuf 格式是项的线性序列;您使用的任何索引等只能单独应用。但是,IEnumerable<T> 可用;你可能会发现:
var item = Serializer.DeserializeItems<YourType>(source)
.First(item => item.Id == id);
做得很好;这个:
或者对于多个项目:
var list = Serializer.DeserializeItems<YourType>(source)
.Where(item => item.Foo == foo);
(如果您想在内存中缓冲匹配项,则在上面的末尾添加一个 ToList,如果您只想以仅转发的方式解析一次,则使用不使用 ToList)
【讨论】:
Serializer.ListItemTag(实际上只是 1) - 前缀样式为 base-128(但无论如何这是默认值)
如果你想在选定的元素列表上添加一些投影,你应该试试我的库,https://github.com/Scooletz/protobuf-linq。它们也可在 NuGet 上使用。 该库大大降低了反序列化的开销。在某些情况下,它可能会下降到原始查询的 50%。
【讨论】:
很遗憾,没有。为了使用 LINQ,您的对象必须实现 IQueryable<T> 或 IEnumerable<T>。除非有 LINQ 提供程序可以在您的 .bin 文件中提供 IQueryable<T> 接口,否则您必须:
IEnumerable<T>
IQueryable<T> 的 LINQ 提供程序(如果您的文件很大,这可能是唯一实用的选择),可以在不加载整个文件的情况下处理文件。【讨论】:
IEnumerable<T> API,那么
yield return) - 非常适合处理大量数据
protobuf 可以将文件内容作为流IEnumerable<T> 提供给您,因此您可以轻松做到这一点。不幸的是,我不知道该方法是如何调用的,但在文档中很容易找到。
【讨论】: