Protobuf-net Guid десериализуется в Guid.Empty при использовании наследования - PullRequest
1 голос
/ 07 октября 2011

У меня проблемы с десериализацией Guid, когда Guid определен в базовом классе сообщений.Когда у меня появляется следующее сообщение.

 [DataContract]
public abstract class GatewayPageEvent:IDomainEvent
{
    protected GatewayPageEvent()
    {
        On = DateTime.Now;
    }
    [DataMember(Order = 1)] public Guid GatewayPageId { get; set; }
    [DataMember(Order = 2)] public DateTime On { get; set; }
}
[DataContract]
public class GatewayPageAddedToSite : GatewayPageEvent
{
    [DataMember(Order = 3)]public string Url { get; set; }
    [DataMember(Order = 4)]public string SiteCode { get; set; }
}

GatewayPageId всегда десериализуется как Guid.Empty.Вот модульный тест, который я написал, который не проходитЯ немного озадачен ...

    public string Serialize(object t)
    {
        var memoryStream = new MemoryStream();
        ProtoBuf.Serializer.Serialize(memoryStream, t);
        return Convert.ToBase64String(memoryStream.ToArray());
    }

    public object Deserialize(string value, Type targetType)
    {
        var bytes = Convert.FromBase64String(value);
        var stream = new MemoryStream(bytes);
        return ProtoBuf.Serializer.NonGeneric.Deserialize(targetType, stream);
    }
    [Test]
    public void protobuf_serialization_can_deserialized_guids()
    {
        var originalMessage = new GatewayPageAddedToSite
                                  {GatewayPageId = Guid.NewGuid(), SiteCode = "dls", Url = "test"};
        var serializedMessage = Serialize(originalMessage);
        var @event = (GatewayPageAddedToSite)Deserialize(serializedMessage, typeof(GatewayPageAddedToSite));
        Assert.AreEqual(@event.GatewayPageId, originalMessage.GatewayPageId);
    }

Я знаю, что гиды работают нормально, потому что следующий модульный тест работает отлично.

[Test]
    public void guids_work_fine()
    {
        var original = Guid.NewGuid();
        var serialized = Serialize(original);
        var deserialized = (Guid) Deserialize(serialized, typeof (Guid));
        Assert.AreEqual(original,deserialized);
    }

Я неправильно определил свой контракт?Или это проблема с protobuf-net?

1 Ответ

0 голосов
/ 07 октября 2011

С protobuf-net он должен знать о наследовании заблаговременно (на самом деле, так же, как и DataContractSerializer, обычно - через [KnownType(...)]). В случае с protobuf-net ему также необходим уникальный ключ для их различения, например:

[DataContract, ProtoInclude(3, typeof(GatewayPageAddedToSite))]
public abstract class GatewayPageEvent:IDomainEvent
{...}
[DataContract]
public class GatewayPageAddedToSite : GatewayPageEvent
{...}

(т. Е. Базовый тип необходимо указать о производных типах)

Обратите внимание, что числа должны быть уникальными в каждом типе , поэтому не существует коллизии между "3" во включении и "3" в GatewayPageAddedToSite - и на самом деле, GatewayPageAddedToSite может использовать «1» и «2», если хочет.

Если модель вашего домена сгенерирована, то может помочь отдельный файл частичного класса:

[ProtoInclude(3, typeof(GatewayPageAddedToSite)]
partial class GatewayPageEvent {}

Если вы действительно не хотите расстраивать вашу модель этими вещами, то в v2 вы можете сделать это во время выполнения:

RuntimeTypeModel.Default[typeof(GatewayPageEvent)]
      .AddSubType(3, typeof(GatewayPageAddedToSite));

что-нибудь из этого заставляет это работать?

...