protobuf-net 使用索引属性时如何避免崩溃

Posted

技术标签:

【中文标题】protobuf-net 使用索引属性时如何避免崩溃【英文标题】:protobuf-net How to avoid crashing when working with Indexed Properties 【发布时间】:2011-10-04 21:10:21 【问题描述】:

我正在尝试将出色的 protobuf-net 集成到现有代码库中,但在尝试处理自定义类型时遇到了崩溃。下面是一个小演示:它将在ProtoBuf.Serializers.ListDecorator 中抛出一个InvalidOperationException。但是,如果您注释掉索引器(或删除 IEnumerable 实现),它就会运行干净。

using System.Collections.Generic;
using ProtoBuf;
using System.Collections;

[ProtoContract]
public class MyClass : IEnumerable<int>    

    [ProtoMember(1, IsPacked = true)]
    public int[] data  get; set; 

    // Comment out this indexed property to prevent the crash
    public int this[int i]  get  return data[i];  set  data[i] = value;  

    public IEnumerator<int> GetEnumerator()  foreach (var x in data) yield return x; 
    IEnumerator IEnumerable.GetEnumerator()  return GetEnumerator(); 

    static void Main(string[] args)  Serializer.PrepareSerializer<MyClass>(); 

我做错了吗?如何告诉 protobuf-net Serializer 忽略 Indexer 属性?

谢谢!

编辑(10 月 10 日):Marc 通过[ProtoContract(IgnoreListHandling = true)] 在protobuf-net r447 中提供了修复。

【问题讨论】:

顺便说一句; [ProtoContract(IgnoreListHandling = true)] 会这样做; r447 现已可供下载 【参考方案1】:

你的类型看起来很像一个集合,而 protobuf-net 确实在尝试这样处理它。一个“修复”是添加一个Add(int) 方法,因为 that 是它在反序列化时想要使用的。但是,我正在调查为什么索引器的存在/不存在在这里会产生影响(这对我来说并不是很明显)。

请注意,因为这看起来很像一个集合,[ProtoMember(...)] 可能不会在这里使用。在找出索引器在这里扮演什么角色之前,我不能 100% 确定。


啊哈; ķ;找到了索引器参与其中的原因——本质上,在检测到IEnumerable 之后,它正在尝试识别集合的Type;它使用各种线索:

ICollection&lt;T&gt; 中的&lt;T&gt; SomeType 中的Add(SomeType) public SomeTime this[int index] ... 索引器中的 SomeType

其中,唯一适用的是最后一个。但是,IMO 它可能还应该在IEnumerable&lt;T&gt; 中使用&lt;T&gt;(我可能会对此进行调整)——这至少会使这种情况不那么奇怪(就像改进错误消息一样,我会这样做)。

总而言之,protobuf-net 对闻起来像集合的东西有很多非常特殊的处理;就个人而言,我会放弃 IEnumerable&lt;T&gt; 支持,而让呼叫者通过 .data 转;该消息将(在某些时候)显示:

无法为 FullName 解析合适的添加方法

【讨论】:

谢谢。真实世界的类型实际上是一种 ArraySegment 类型的东西,显示了底层数组的有限视图。所以 IEnumerable 的实现并不简单地暴露数组。那些“提示”在 TypeModel.ResolveListAdd() 中,对吧?我可能会尝试破解一下... @Gabriel 这是GetListItemType 的问题 啊,是的,我现在明白了。谢谢! @Gabriel 澄清一下,我在这里的首选选择是找出某种机制来说“这确实是一个对象;忽略所有列表处理”,而不是对那个方法大惊小怪 可能类似于ProtoContractAttribute 中的bool NotAList 属性?

以上是关于protobuf-net 使用索引属性时如何避免崩溃的主要内容,如果未能解决你的问题,请参考以下文章

如何将 protobuf-net 与通过 ASP.NET Web Reference 生成的类一起使用,同时避免代码重复?

如何避免单点风险:基于实践经验分享服务拆分原则的一些思考

Protobuf-Net:如何序列化 guid?

protobuf-net:如何注释派生类型的属性?

使用带有标志枚举的 ProtoBuf-Net 时出错

我可以重复使用对象实例来避免使用 protobuf-net 进行分配吗?