【发布时间】:2010-04-10 05:28:48
【问题描述】:
我在使用 protobuf-net 反序列化 ORM 生成的实体的某些 Guid 属性时遇到问题。
这是代码的简化示例(重现了场景的大部分元素,但没有重现行为;我无法公开我们的内部实体,因此我正在寻找解释异常的线索)。假设我有一堂课,Account 有一个 AccountID 只读 guid 和一个 AccountName 读写字符串。我序列化并立即反序列化一个克隆。
反序列化时会引发Incorrect wire-type deserializing Guid 异常。
这里是示例用法...
Account acct = new Account() { AccountName = "Bob's Checking" };
Debug.WriteLine(acct.AccountID.ToString());
using (MemoryStream ms = new MemoryStream())
{
ProtoBuf.Serializer.Serialize<Account>(ms, acct);
Debug.WriteLine(Encoding.UTF8.GetString(ms.GetBuffer()));
ms.Position = 0;
Account clone = ProtoBuf.Serializer.Deserialize<Account>(ms);
Debug.WriteLine(clone.AccountID.ToString());
}
这是一个 ORM 类的示例(经过简化,但演示了我能想到的相关语义)。使用 shell 游戏通过暴露支持字段来反序列化只读属性(“不能写”本质上变成“不应该写”,但我们可以扫描代码以获取分配给这些字段的实例,因此该 hack 适用于我们的目的)。
同样,这不会重现异常行为;我正在寻找关于可能的线索:
[DataContract()]
[Serializable()]
public partial class Account
{
public Account()
{
_accountID = Guid.NewGuid();
}
[XmlAttribute("AccountID")]
[DataMember(Name = "AccountID", Order = 1)]
public Guid _accountID;
/// <summary>
/// A read-only property; XML, JSON and DataContract serializers all seem
/// to correctly recognize the public backing field when deserializing:
/// </summary>
[IgnoreDataMember]
[XmlIgnore]
public Guid AccountID
{
get { return this._accountID; }
}
[IgnoreDataMember]
protected string _accountName;
[DataMember(Name = "AccountName", Order = 2)]
[XmlAttribute]
public string AccountName
{
get { return this._accountName; }
set { this._accountName = value; }
}
}
XML、JSON 和 DataContract 序列化器似乎都可以很好地序列化/反序列化这些对象图,因此属性排列基本有效。我已经尝试过使用列表与单个实例、不同前缀样式等的 protobuf-net,但在反序列化时仍然总是得到“不正确的线型 ... Guid”异常。
所以具体的问题是,是否有任何已知的解释/解决方法?我不知道是什么情况(在实际代码中但不是示例中)可能导致它。
我们希望不必直接在实体层创建protobuf依赖;如果是这种情况,我们可能会创建代理 DTO 实体,其中所有公共属性都具有 protobuf 属性。 (这是我对所有声明性序列化模型的主观问题;这是一种普遍存在的模式,我理解它为什么会出现,但是 IMO,如果我们可以将人送上月球,那么“正常”应该是拥有对象和序列化合同解耦。;-) )
谢谢!
【问题讨论】:
-
@Paul - 只是基于您的调试行的一个随机想法......您是否在任何时候将二进制文件视为字符串?那行不通:marcgravell.blogspot.com/2010/03/binary-data-and-strings.html
-
@marc - 合理的检查,但不,字符串输出只是为了快速的视觉增量。答案线程中的其他 cmets。谢谢!
标签: c# protobuf-net