gpt4 book ai didi

c# - 用 protobuf 替换 binaryformatter

转载 作者:太空宇宙 更新时间:2023-11-03 21:32:14 27 4
gpt4 key购买 nike

我需要替换一个在文件中存储数据的库(序列化/反序列化)这个库目前使用 BinaryFormatter 来做,但对于大列表来说速度很慢。stackoverflow 上的许多帖子都表明 protobuf 确实非常高效,所以我正在尝试使用它。

为了在不重写大量代码的情况下进行替换,我的要求是:

  • 必须序列化通用数据,因为我必须与 Store<T>(T data) 交互(大多数时候 T 被标记为 DataContract 和/或 Serializable 属性)
  • 我无法修改所有不同的对象类来添加 protobuf 属性,因此我需要一个不使用这些属性的通用方法
  • 我不需要向后兼容性:如果 T 对象模式发生变化(即新属性),所有生成的文件都已过时,将被删除/重新创建

我的第一个天真的实现是这样的:

public bool Store<T>(string key, T data)
{
var formatter = Serializer.CreateFormatter<T>();
using (var fileStream = new FileStream(this.GetFilePath(key), FileMode.Create))
{
formatter.Serialize(fileStream, data);
return true;
}
}

但是后来我得到了这个异常:

Type is not expected, and no contract can be inferred: My.Application.Namespace.ShortcutData

目前我有点卡住了,我没有找到关于如何使用 protobuf-net 的好的教程。

是否可以使用 protobuf 达到这些要求?您是否有关于如何执行此操作的良好教程?

编辑:

问题确实是我需要告诉 protobuf 如何(反)序列化数据。这是我现在拥有的:

public bool Store<T>(string key, T data)
{
this.Register<T>();
var formatter = Serializer.CreateFormatter<T>();
using (var fileStream = new FileStream(this.GetFilePath(key), FileMode.Create))
{
formatter.Serialize(fileStream, data);
fileStream.Close();
return true;
}
}

主要代码在Register方法中:

protected void Register(Type type)
{
if (type.IsGenericType)
{
var arguments = type.GetGenericArguments();
foreach (var argument in arguments)
this.Register(argument);
}

if (!this._registeredTypes.Contains(type) && !type.IsValueType)
{
this._registeredTypes.Add(type);
var properties = type.GetProperties();
foreach (var property in properties)
{
this.Register(property.PropertyType);
}

try
{
ProtoBuf.Meta.RuntimeTypeModel.Default
.Add(type, false)
.Add(properties
.Where( p => p.CanWrite)
.OrderBy(x => x.Name)
.Select(x => x.Name)
.ToArray());
}
catch
{
// I've a problem here: I sometime have an error for an already registered type (??)
}
}
}

我知道这不是一个干净的代码,但这只是对现有代码的替换,第二步将考虑到 protobuf 的完整重写。

最佳答案

我才刚刚开始玩 Protobuf-net.. 所以请不要假设我的回答在任何方面都是“正确”的做事方式。 Marc Gravell 无疑会在某个时候为您提供您绝对应该注意的答案。

..然而,我前几天写的概念证明要求我快速地序列化一大堆类。为此……我想到了这个:

var assembly = Assembly.Load("Assembly.Name.Here");

foreach (var type in assembly.GetTypes().Where(x => typeof (IInterfaceEachClassImplements).IsAssignableFrom(x))) {
RuntimeTypeModel
.Default
.Add(type, false)
.Add(type.GetProperties()
.Select(x => x.Name)
.ToArray());
}

基本上,它根据每个类都实现的接口(interface)将每个类加载到 protobuf-net 类型模型中……而不是应用于它们的属性。

无论如何,希望这能为您指明正确的方向。

关于c# - 用 protobuf 替换 binaryformatter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23620142/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com