序列化树“生成序列化程序后无法更改类型”

时间:2012-03-16 09:49:52

标签: protobuf-net

我尝试序列化一个由Craft或Reagent组成的树:

[ProtoContract]
[ProtoInclude(1, typeof(Craft))]
[ProtoInclude(2, typeof(Reagent))]
public interface IReagent : IEquatable
{
    [ProtoMember(1)]
    int ItemId { get; set; }
    [ProtoMember(2)]
    int Quantity { get; set; }
}

[ProtoContract] public class Reagent : IReagent { [ProtoMember(1)] public int ItemId { get; set; } [ProtoMember(2)] public int Quantity { get; set; } }

[ProtoContract] public class Craft : IReagent { [ProtoMember(1)] public int Skill { get; set; }

[ProtoMember(2)]
public Profession Profession { get; set; }

[ProtoMember(3)]
public List<IReagent> Reagents { get; set; }

[ProtoMember(4)]
public int ItemId { get; set; }

[ProtoMember(5)]
public int Quantity { get; set; }

}

序列化代码:

[ProtoMember(2)]
public Profession Profession { get; set; }

[ProtoMember(3)]
public List<IReagent> Reagents { get; set; }

[ProtoMember(4)]
public int ItemId { get; set; }

[ProtoMember(5)]
public int Quantity { get; set; }

测试代码:

public class ProtobufMessageSerializer<T> : ISerializer<T> {
    private readonly ILog logger;

    public ProtobufMessageSerializer(ILog logger)
    {
        this.logger = logger;
    }

    public byte[] Serialize(T entity)
    {
        byte[] message = new byte[0];

        try
        {
            using (var ms = new MemoryStream())
            {
                Serializer.Serialize(ms, entity);
                message = ms.ToByteArray();
            }


            logger.Info(string.Format("Serialized message with a length of: {0}", message.GetHumanReadableSize()));
        }
        catch (Exception ex)
        {
            logger.Warn(ex);
        }


        return message;
    }

    public T Deserialize(byte[] message)
    {
        T result = default(T);

        try
        {
            using (var ms = new MemoryStream(message))
            {
                result = Serializer.Deserialize<T>(ms);
            }

        }
        catch (Exception ex)
        {
            logger.Warn(ex);
        }


        return result;
    }
}

序列化后,我得到:

[Test] public void TestSerializer() { var responseSerializer = container.Resolve<ISerializer<IReagent>>(); var repos = container.Resolve<CraftRepository>(); var craft = repos.GetAll().First(); var serializedForm = responseSerializer.Serialize(craft); var deserializedForm = responseSerializer.Deserialize(serializedForm); Assert.NotNull(deserializedForm); }

堆栈跟踪:

The type cannot be changed once a serializer has been generated for Bargains.Data.Craft (Bargains.Data.IReagent)

1 个答案:

答案 0 :(得分:2)

基本上,界面支持目前只扩展到成员;我应该以这种方式使用serialzie / deserialize是错误的,或者让它工作! (后者显然更可取)。

如果你引入一个包装器,如:

[ProtoContract]
public class Wrapper {
    [ProtoMember(1)]
    public IReagent Reagent {get;set;}
}

并序列化 ,然后它应该工作。您还需要修复以下损坏的合同:

[ProtoContract]
[ProtoInclude(1, typeof(Craft))]
[ProtoInclude(2, typeof(Reagent))]
public interface IReagent 
{
    [ProtoMember(3)] // <==== was 1
    int ItemId { get; set; }
    [ProtoMember(4)] // <==== was 2
    int Quantity { get; set; }
}

(这些数字不能在单一类型中重复)