protobuf-net:反序列化 Guid 属性时出现错误的线路类型异常

发布于 2024-08-28 12:27:54 字数 2268 浏览 3 评论 0原文

我在使用 protobuf-net 反序列化 ORM 生成的实体的某些 Guid 属性时遇到问题。

这是代码的简化示例(重现场景的大多数元素,但不重现行为;我无法公开我们的内部实体,因此我正在寻找线索来解释异常)。假设我有一个类 Account,其中包含 AccountID 只读 GUID 和 AccountName 读写字符串。我连载&立即反序列化克隆。

反序列化时,反序列化会引发不正确的线类型反序列化 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 游戏通过暴露支持字段来反序列化只读属性(“不能写”本质上变成“不应该写”,但我们可以扫描代码以查找分配给这些字段的实例,因此该黑客适用于我们目的)。

同样,这不会重现异常行为;我正在寻找关于可以做什么的线索:

[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 属性。 (这是我对所有声明性序列化模型的一个主观问题;这是一种普遍存在的模式,我理解它出现的原因,但在我看来,如果我们可以把一个人送上月球,那么“正常”应该是拥有对象和序列化合同解耦。;-))

谢谢!

I'm having issues deserializing certain Guid properties of ORM-generated entities using protobuf-net.

Here's a simplified example of the code (reproduces most elements of the scenario, but doesn't reproduce the behavior; I can't expose our internal entities, so I'm looking for clues to account for the exception). Say I have a class, Account with an AccountID read-only guid, and an AccountName read-write string. I serialize & immediately deserialize a clone.

Deserializing throws an Incorrect wire-type deserializing Guid exception while deserializing.

Here's example usage...

        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());
        }

And here's an example ORM'd class (simplified, but demonstrates the relevant semantics I can think of). Uses a shell game to deserialize read-only properties by exposing the backing field ("can't write" essentially becomes "shouldn't write," but we can scan code for instances of assigning to these fields, so the hack works for our purposes).

Again, this does not reproduce the exception behavior; I'm looking for clues as to what could:

[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 and DataContract serializers all seem to serialize / deserialize these object graphs just fine, so the attribute arrangement basically works. I've tried protobuf-net with lists vs. single instances, different prefix styles, etc., but still always get the 'incorrect wire-type ... Guid' exception when deserializing.

So the specific questions is, is there any known explanation / workaround for this? I'm at a loss trying to trace what circumstances (in the real code but not the example) could be causing it.

We hope not to have to create a protobuf dependency directly in the entity layer; if that's the case, we'll probably create proxy DTO entities with all public properties having protobuf attributes. (This is a subjective issue I have with all declarative serialization models; it's a ubiquitous pattern & I understand why it arose, but IMO, if we can put a man on the moon, then "normal" should be to have objects and serialization contracts decoupled. ;-) )

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

小巷里的女流氓 2024-09-04 12:27:54

同意,您不需要显式依赖项 - DataMember 就可以了。 protobuf-net 使用相同的逻辑重新忽略等。您如何/在哪里存储数据?根据我的经验,最常见的原因是人们用不同的数据覆盖缓冲区(或文件),而不是截断它(在流末尾留下垃圾),如此处讨论。这与您的场景有关吗?

Agreed, you shouldn't need an explicit dependency - DataMember is fine. And protobuf-net uses the same logic re ignore etc. How / where are you storing the data? In my experience the most common cause of this is that people are over-writing a buffer (or file) with different data, and not truncating it (leaving garbage at the end of the stream), as discussed here. Is this related to your scenario?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文