我在使用 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'd 类(简化,但演示了我能想到的相关语义)。使用 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,如果我们可以将一个人送上月球,那么“正常”应该是拥有对象和序列化合同解耦。;-) )
谢谢!