异常序列化自定义集合 [英] Exception serializing custom collection

查看:52
本文介绍了异常序列化自定义集合的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感谢伟大的图书馆 Marc 以及所有关于 SO 的答案.

Thanks for the great library Marc and for all the answers on SO.

我在 .NET 4.0.zip 上使用 protobuf-net r480.zip 来自 http://code.google.com/p/protobuf-net/downloads/list.这是最新的稳定版本吗?

I'm using protobuf-net r480.zip on .NET 4.0.zip from http://code.google.com/p/protobuf-net/downloads/list. Is this the latest stable release?

我在序列化自定义集合时遇到问题.

I'm having trouble serializing a custom collection.

public static void TestSerialization() {
    using (var stream = new MemoryStream()) {
        var b1 = new B1 { 1 };
        // Throws System.ArgumentException: Repeated data (a list, collection, etc) has inbuilt behaviour and cannot be subclassed
        Serializer.Serialize(stream, b1);
    }

    using (var stream = new MemoryStream()) {
        var b2 = new B2 { 2 };
        Serializer.Serialize(stream, b2);
        stream.Position = 0;
        var b2Deserialized = Serializer.Deserialize<B2>(stream);

        // This fails because b2Deserialized.Count is 0.
        Assert.AreEqual(1, b2Deserialized.Count);
    }

    using (var stream = new MemoryStream()) {
        RuntimeTypeModel.Default[typeof(A2<int>)].AddSubType(1000, typeof(B2));
        var b2 = new B2 { 2 };
        // Throws System.ArgumentException: Repeated data (a list, collection, etc) has inbuilt behaviour and cannot be subclassed
        Serializer.Serialize(stream, b2);
    }
}

[ProtoContract]
[ProtoInclude(1000, typeof(B1))]
public class A1<T> : List<T> { }

[ProtoContract]
public class B1 : A1<int> { }

[ProtoContract]
public class A2<T> : List<T> { }

[ProtoContract]
public class B2 : A2<int> { }

感谢 Marc 的回答,如果只使用列表,删除 Proto 属性效果很好.不幸的是,实际代码更复杂 - 派生集合包含其他值(在实际代码中,模板参数为 Entity 而不是 int 类型,并且集合中的成员是对集合中元素的父级的引用).这是一个更好的表示.

Thanks for the anser Marc, removing the Proto attributes works great if just using a list. Unfortunately, the actual code is more complex - the derived collection contains other values (in the real code the template parameter in of type Entity instead of int and the member in the collection is a reference to the parent of the elements in the collection). Here is a better representation.

    public static void TestSerialization() {
        using (var stream = new MemoryStream()) {
            var b = new B { 23 };
            b.SomeValue = "abc";
            Serializer.Serialize(stream, b);

            stream.Position = 0;
            var deserialized = Serializer.Deserialize<B>(stream);
            Assert.AreEqual(1, deserialized.Count);
            Assert.AreEqual(b[0], deserialized[0]);

            // This fails because deserialized.SomeValue == null
            Assert.AreEqual(b.SomeValue, deserialized.SomeValue);
        }
    }

    public class A<T> : List<T> { }

    public class B : A<int>
    {
        [ProtoMember(1)]
        public string SomeValue;
    }

推荐答案

IMO 错误消息非常清楚:列表不支持继承.这是因为列表没有占位符,因此无处存储此信息.在 XML 术语中(注意 protobuf 与 XML 完全不同),它就像(如果您熟悉 XmlSerializer)的输出:

IMO the error message is quite clear: inheritance is not supported on lists. This is because lists don't have a place-holder, so there is nowhere to store this information. In XML terms (noting that protobuf is nothing like XML), it is like the output of (if you are familiar with XmlSerializer):

[XmlElement("item")]
public List<Foo> Items { get; set; }

哪些输出只是:

<item>...</item>
<item>...</item>
<item>...</item>

(但没有项目"节点 - 没有任何地方可以说明列表本身)

(but no "Items" node - there exists nowhere that you could say anything about the list itself)

我试图理解您试图用该继承来表示什么.坦率地说,我没有看到任何有用的东西——因为列表具有内置行为,你根本不需要为这些定义契约;只需将它们用作列表即可.

I'm trying to understand what you are trying to represent with that inheritance. Frankly, I'm not seeing anything useful - since lists have inbuilt behaviour, you don't need to define contracts for these at all; just use them as lists.

一般来说,封装列表通常更好,而不是继承它们.

In the general sense, it is usually better to encapsulate lists, not inherit them.

这篇关于异常序列化自定义集合的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆