我正在使用C#
撰写protobuf-net
上的项目。我有代码将Dictionary<MyClass1, MyClass2>
序列化/反序列化为文件。另外,我有一个包含序列化数据的文件。当我尝试反序列化时,我收到异常key
无法null
。由于Dictionary
不允许null
,我不明白它是如何可能的,看起来我无法序列化这样的词典。我认为该文件已损坏,但我不确定。我试图调试它,看起来几个键和值被正确反序列化,但在反序列化过程中,null
键出现,我看到异常。我尝试使用ProductName
代理here,但它没有帮助。
如何反序列化此文件?
可能有一种方法可以反序列化到某个对象,而不是null
的{{1}}吗?
例外:
System.ArgumentNullException:值不能为null。 参数名称:key 在System.Collections.Generic.Dictionary
ProductName
2.System.Collections.Generic.ICollection&gt; .Add(KeyValuePair`2 keyValuePair) 在proto_10(Object,ProtoReader) at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader,Type type,Object value,Boolean noAutoCreate)in c:\ Dev \ protobuf-net \ protobuf-net \ Meta \ TypeModel.cs:line 704 at ProtoBuf.Meta.TypeModel.Deserialize(流源,对象值,类型类型,SerializationContext上下文)在c:\ Dev \ protobuf-net \ protobuf-net \ Meta \ TypeModel.cs:第588行 在ProtoBuf.Serializer.Deserialize [T](流源)c:\ Dev \ protobuf-net \ protobuf-net \ Serializer.cs:第77行
代码:
2.Insert(TKey key, TValue value, Boolean add)
at System.Collections.Generic.Dictionary
答案 0 :(得分:0)
首先,要测试文件是否确实已损坏,您可以尝试按照Recovering corrupted file serialize with Protobuf-net中的说明检查文件是否已损坏。
接下来,无论文件是否损坏,要尽可能反序列化,您可以使用Serializer.Merge<T>(Stream source, T instance)
将文件合并到预先分配的ProductNameIndex
上,如下所示:
var index = new ProductNameIndex();
try
{
Serializer.Merge(stream, index);
}
catch (Exception ex)
{
// Log the error
Debug.WriteLine(ex);
}
index
现在应包含尽可能多的条目,以便完全反序列化。
现在,如果文件 损坏,除非您想将其加载到MemoryStream
并尝试逐字节手动修复,否则这可能是您可以做的最好的事情。 。但是如果文件不损坏,则需要调试以找出问题所在。要采取的一项措施是将为ProductNameIndex
生成的合同与文件中实际使用的合同进行比较。要查看ProductNameIndex
的合同,您可以执行以下操作:
Debug.WriteLine(ProtoBuf.Meta.RuntimeTypeModel.Default.GetSchema(typeof(ProductNameIndex)));
然后比较Recovering corrupted file serialize with Protobuf-net的输出,我相信只转储顶级字段。如果字段编号和连线类型不匹配,您将知道您正在读取其根对象实际上不是ProductNameIndex
的文件。您还可以使用GetSchema()
中的合同infortmation手动进入重复字段(字符串)和嵌套对象。
最后,如果合同匹配,但发送系统发出KeyValuePair_ProductName_ProductId
消息时遗漏了optional ProductName Key
,您可以修改ProductNameIndex
以使用代理项忽略此类无效条目数组属性:
[DataContract]
[ProtoContract]
public class ProductNameIndex
{
[ProtoMember(1, Name = "Products")]
KeyValuePair<ProductName, ProductId>[] ProductsSurrogateArray
{
get
{
return Products.ToArray();
}
set
{
if (value == null)
return;
foreach (var p in value)
{
if (p.Key == null)
Debug.WriteLine("Ignoring invalid null key");
else
Products.Add(p);
}
}
}
[ProtoIgnore]
[DataMember(Order = 1)]
public IDictionary<ProductName, ProductId> Products { get; private set; }
public ProductNameIndex()
{
this.Products = new Dictionary<ProductName, ProductId>();
}
}
或者,如果您无法为您的类型添加protobuf属性,您可以为ProductNameIndex
引入代理类型并进行必要的检查,如here所述。
最后,看看Using Protobuf-net, I suddenly got an exception about an unknown wire-type,它有一些诊断protobuf-net问题的有用建议,包括:
最可能的原因(根据我的经验)是您已覆盖现有文件,但未截断它;即它是200字节;你重写了它,但只有182个字节。现在流的末尾有18个字节的垃圾正在绊倒它。重写协议缓冲区时必须截断文件。