【问题标题】:Protobuf-net dynamictype arrayProtobuf-net 动态类型数组
【发布时间】:2013-07-13 10:18:06
【问题描述】:

我不会使用 Protobuf-net 进行一些序列化,并且此代码 sn-p 会出现以下错误:

错误:

动态类型不是合约类型:TestType[]

sn-p:

using System.IO;
namespace QuickStart
{
    class Program
    {
        static void Main()
        {
            //FileAccess.ShowFileAccess();
            //Sockets.ShowSockets();

            var dto = new DataTransferType
            {
                ProtoDynamicProperty = new TestType[]
                {
                    new TestType {UselessProperty="AAA"},
                    new TestType{UselessProperty="BBB"},
                    new TestType{UselessProperty="CCC"}
                }
            };

            using (MemoryStream testStream = new MemoryStream())
            {
                ProtoBuf.Serializer.SerializeWithLengthPrefix(testStream, dto, ProtoBuf.PrefixStyle.Base128);
            }
        }


    }
    [ProtoBuf.ProtoContract]
    struct TestType
    {
        [ProtoBuf.ProtoMember(1)]
        public string UselessProperty { get; set; }
    }

    [ProtoBuf.ProtoContract]
    class DataTransferType
    {
        [ProtoBuf.ProtoMember(1, DynamicType = true)]
        public object ProtoDynamicProperty { get; set; }
    }
}

任何想法为什么会发生这种情况?我正在使用 2.0.0.651 构建

【问题讨论】:

  • 刚刚回答了this question,我意识到我也知道这个老问题的答案,所以我继续回答它,尽管它已经很老了。

标签: object serialization protobuf-net dynamictype


【解决方案1】:

former project site protobuf-net 中提到的hereDynamicType 的限制解释了您的困难(尽管不完全):

DynamicType - 使用类型存储附加的Type 信息(默认情况下它包括AssemblyQualifiedName,尽管这可以由用户控制)。这使得序列化弱模型成为可能,即 object 用于属性成员,但是目前这仅限于 contract 类型(不是原语),并且不适用于具有继承的类型(这些限制可能会在以后删除)。与AsReference 一样,它使用非常不同的布局格式。

那么,究竟是什么意思合同类型?如前所述,原始类型不是合同类型,但仅此而已吗?来自Protobuf-net: the unofficial manual: Forms of type serialization in protobuf-net

我会说 protobuf-net 在逐个类型的基础上支持五种基本的 [反] 序列化(不包括原始类型):

  1. 正常序列化。在此模式下,将写入标准协议缓冲区,协议缓冲区中的一个字段用于您使用 ProtoMember 标记的每个字段或属性,或者已由 ImplicitFields 自动选择。 ...

  2. 集合序列化。如果 protobuf-net 将特定数据类型标识为集合,则使用此模式对其进行序列化。值得庆幸的是,集合类型不需要任何 ProtoContract 或 ProtoMember 属性,这意味着您可以轻松序列化 List 和 T[] 等类型...

    <snip>

    Protobuf-net 使用“重复”字段(在协议缓冲区术语中)序列化集合。因此,您应该能够在版本之间安全地更改集合类型。例如,您可以将 Foo[] 序列化,然后将其反序列化为 List。

因此,“合约类型”的序列化对应于本文中的“正常序列化”——而集合不是合约类型。这解释了Dynamic type is not a contract-type: TestType[] 异常消息。

作为一种解决方法,您可以将ProtoDynamicProperty 封装在一个通用代理类型中,该代理类型保证与合同类型相对应并封装必要的类型信息,如下所示:

[ProtoContract]
public abstract class TypedObjectSurrogate
{
    protected TypedObjectSurrogate() { }

    [ProtoIgnore]
    public abstract object ObjectValue { get; }

    public static object CreateSurrogate<T>(T value)
    {
        if (value == null)
            return new TypedObjectSurrogate<T>();
        var type = value.GetType();
        if (type == typeof(T))
            return new TypedObjectSurrogate<T>(value);
        // Return actual type of subclass
        return Activator.CreateInstance(typeof(TypedObjectSurrogate<>).MakeGenericType(type), value);
    }
}

[ProtoContract]
public sealed class TypedObjectSurrogate<T> : TypedObjectSurrogate
{
    public TypedObjectSurrogate() : base() { }

    public TypedObjectSurrogate(T value)
        : base()
    {
        this.Value = value;
    }

    [ProtoIgnore]
    public override object ObjectValue
    {
        get { return Value; }
    }

    [ProtoMember(1)]
    public T Value { get; set; }
}

[ProtoBuf.ProtoContract]
class DataTransferType
{
    [ProtoBuf.ProtoIgnore]
    public object ProtoDynamicProperty { get; set; }

    [ProtoBuf.ProtoMember(1, DynamicType = true)]
    object ProtoDynamicPropertySurrogate
    {
        get
        {
            if (ProtoDynamicProperty == null)
                return null;
            return TypedObjectSurrogate.CreateSurrogate(ProtoDynamicProperty);
        }
        set
        {
            if (value is TypedObjectSurrogate)
                ProtoDynamicProperty = ((TypedObjectSurrogate)value).ObjectValue;
            else
                ProtoDynamicProperty = value;
        }
    }
}

[ProtoBuf.ProtoContract]
struct TestType
{
    [ProtoBuf.ProtoMember(1)]
    public string UselessProperty { get; set; }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多