当在消息基类中定义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);
}
我知道Guids工作正常,因为以下单元测试工作正常。
[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的问题吗?
答案 0 :(得分:0)
使用protobuf-net,它需要提前了解继承(实际上DataContractSerializer
通常也是如此 - 通过[KnownType(...)]
)。在protobuf-net的情况下,它还需要一个唯一的键来区分它们,例如:
[DataContract, ProtoInclude(3, typeof(GatewayPageAddedToSite))]
public abstract class GatewayPageEvent:IDomainEvent
{...}
[DataContract]
public class GatewayPageAddedToSite : GatewayPageEvent
{...}
(即需要告知基类型派生类型)
请注意,每个类型中的数字只需要唯一,因此包含中的“3”与GatewayPageAddedToSite
中的“3”之间不会发生冲突 - 实际上,如果需要,GatewayPageAddedToSite
可以使用“1”和“2”。
如果您的域模型已生成,则单独的部分类文件可能有所帮助:
[ProtoInclude(3, typeof(GatewayPageAddedToSite)]
partial class GatewayPageEvent {}
如果你真的不想用这些东西打乱你的模型,那么在v2中你可以在运行时这样做:
RuntimeTypeModel.Default[typeof(GatewayPageEvent)]
.AddSubType(3, typeof(GatewayPageAddedToSite));
任何一个使它有用吗?