Сериализация дерева «Тип не может быть изменен после генерации сериализатора» - PullRequest
2 голосов
/ 16 марта 2012

Я пытаюсь сериализовать дерево, которое состоит из Craft или Реагента:

[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; }
}</p>

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

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

<pre><code>[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)

Stacktrace:

at ProtoBuf.Meta.MetaType.ThrowIfFrozen() in C:\Dev\protobuf-net\protobuf-net\Meta\MetaType.cs:line 256
   at ProtoBuf.Meta.MetaType.AddSubType(Int32 fieldNumber, Type derivedType) in C:\Dev\protobuf-net\protobuf-net\Meta\MetaType.cs:line 70
   at ProtoBuf.Meta.MetaType.ApplyDefaultBehaviour() in C:\Dev\protobuf-net\protobuf-net\Meta\MetaType.cs:line 432
   at ProtoBuf.Meta.RuntimeTypeModel.FindOrAddAuto(Type type, Boolean demand, Boolean addWithContractOnly, Boolean addEvenIfAutoDisabled) in C:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 202
   at ProtoBuf.Meta.RuntimeTypeModel.GetKey(Type type, Boolean demand, Boolean getBaseKey) in C:\Dev\protobuf-net\protobuf-net\Meta\RuntimeTypeModel.cs:line 369

1 Ответ

2 голосов
/ 16 марта 2012

В основном, поддержка интерфейса в настоящее время распространяется только на членов ; Я должен сделать ошибку, чтобы использовать 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; }
}

(числа не могут быть продублированы внутри одного типа)

...