将自定义IEnumerable <t>序列化为字段无法正常工作</t>

时间:2015-04-14 20:16:45

标签: c# serialization protobuf-net

我有一个自定义集合,如下所示:

class SpecialReadOnlyCollection<T> : IReadOnlyCollection<T>{
    private readonly List<T> entries;
    public SpecialReadOnlyCollection(IEnumerable<T> source){
        entries = new List<T>(source);
    }
    ...
}

那(除其他外)包装了一个列表,但没有提供Add方法。

现在我有两个其他类:

class A{
    public string Name;
    public int Value;
}

class ContainerOfA{
    public SpecialReadOnlyCollection<A> list;

    public ContainerOfA(IEnumerable<A> source){
        this.list = new SpecialReadOnlyCollection<A>(source);
    }
}

我想序列化ContainerOfA。由于我不喜欢属性,因此我就是如何构建模型并尝试序列化的。

    // Make A serializable
var metaType = Model.Add(typeof(A),true);
metaType.AddField(1,"Name");
metaType.AddField(2,"Value");
metaType.UseConstructor = false;

// Make SpecialCollection serializable
Model.Add(typeof(SpecialReadOnlyCollection<A>),true).AddField(1,"entries");
Model[typeof(SpecialReadOnlyCollection<A>)].IgnoreListHandling = true;
Model[typeof(SpecialReadOnlyCollection<A>)].UseConstructor = false;

// Make container serializable
Model.Add(typeof(ContainerOfA),true).AddField(1,"list");
Model[typeof(ContainerOfA)].UseConstructor = false; 

// Initialize the container
A a = new A{Name ="Name", Value =1};
A[] arr = {a};
var container = new ContainerOfA(arr);

// Try and serialize .... 
Model.DeepClone(container);

然而,当我尝试序列化时,我得到一个例外:

Unable to resolve a suitable Add method for SpecialReadOnlyCollection[A]

我觉得奇怪的是,如果我尝试序列化列表,它可以正常工作:

Model.DeepClone(container.list);

如果我不是在代码使用属性中构建模型,那么一切正常。事实上,如果我仅在ContainerOfA中使用属性并使ASpecialReadOnlyCollection可通过代码进行序列化,则一切正常。

我做错了吗?我怎么能绕过这个? (可能最简单的答案是使用属性......但我真的想避免属性)。

tl; dr:如何通过RuntimeTypeModel使用protobuf-net序列化一个类,该类具有不应被视为列表的IEnumerable成员(IgnoreListHandling = true)。

1 个答案:

答案 0 :(得分:0)

protobuf-net支持一系列列表模式;在您的情况下,它正在尝试使用IEnumerable<T>/GetEnumerator()Add(T)模式。它需要两者IEnumerable<T>/GetEnumerator()用于序列化,Add(T)用于反序列化。如果您的自定义集合没有明显的Add(T)方法,那么protobuf-net将拒绝使用该集合,因为它将无法反序列化。这就是方法告诉你的。

解决这个问题的唯一方法可能是使用可变DTO模型,而不是这个只读集合。 类似于protobuf-net支持的隐式类型转换之类的东西,但不支持这种情况。