【发布时间】:2014-05-12 22:44:46
【问题描述】:
我需要替换将数据存储在文件中的库(序列化/反序列化) 这个库目前使用 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;
}
}
但后来我得到了这个例外:
类型不是预期的,也不能推断出任何契约: 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 的完全重写。
【问题讨论】:
标签: c# c#-4.0 protobuf-net