4

我正在尝试将很棒的 protobuf-net 集成到现有的代码库中,但是当它尝试处理自定义类型时遇到了崩溃。下面是一个小演示:它将抛出一个InvalidOperationException. ProtoBuf.Serializers.ListDecorator但是,如果您注释掉索引器(或删除 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 友好地通过.protobuf-net r447[ProtoContract(IgnoreListHandling = true)]提供了修复。

4

1 回答 1

4

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

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


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

  • <T>在_ICollection<T>
  • SomeType在_Add(SomeType)
  • 在索引器SomeTypepublic SomeTime this[int index] {...}

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

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

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

于 2011-10-04T21:20:06.460 回答