protobuf-net不会反序列化DateTime.Kind正确]]

问题描述 投票:19回答:7

使用protobuf-net.dll版本1.0.0.280

[当我反序列化DateTime(包装在对象中)时,日期/时间确定,但是DateTime.Kind属性为“未指定”

考虑此测试用例以序列化/反序列化DateTime。

[TestMethod]
public void TestDateTimeSerialization()
{
    var obj = new DateTimeWrapper {Date = DateTime.UtcNow};
    obj.Date = DateTime.SpecifyKind(obj.Date, DateTimeKind.Utc);
    var serialized = obj.SerializeProto();
    var deserialized = serialized.DeserializeProto<DateTimeWrapper>();
    Assert.AreEqual(DateTimeKind.Utc, deserialized.Date.Kind);
}

public static byte[] SerializeProto<T>(this T item) where T : class
{
    using (var ms = new MemoryStream())
    {
        Serializer.Serialize(ms, item);
        return ms.ToArray();
    }
}

public static T DeserializeProto<T>(this byte[] raw) where T : class, new()
{
    using (var ms = new MemoryStream(raw))
    {
        return Serializer.Deserialize<T>(ms);
    }
}

断言失败,种类== Unspecified

附录

由于protobuf-net未序列化此属性(请参见下文),一种解决方案是假设在客户端显示日期时DateTimeKind等于Utc(仅当您know应该为UTC时)课程):

public static DateTime ToDisplayTime(this DateTime utcDateTime, TimeZoneInfo timezone)
{
    if (utcDateTime.Kind != DateTimeKind.Utc)//may be Unspecified due to serialization
        utcDateTime = DateTime.SpecifyKind(utcDateTime, DateTimeKind.Utc);
    DateTime result = TimeZoneInfo.ConvertTime(utcDateTime, timezone);
    return result;
}

这省去了您分配给接收方的每个DateTime属性的麻烦。

使用protobuf-net.dll版本1.0.0.280,当我反序列化DateTime(包装在对象中)时,日期/时间确定,但是DateTime.Kind属性为'Unspecified'将此测试用例考虑为...

c# .net serialization protobuf-net globalization
7个回答
7
投票

protobuf.net必须保持与protobuf二进制格式的兼容性,该格式是为Java日期/时间数据类型设计的。 Java中没有Kind字段->没有protobuf二进制格式的Kind支持-> Kind未通过网络传输。或类似的东西。


5
投票

作为Ben答案的扩展...严格来说,protobuf


2
投票

另一种解决方案是更改DTO的kind属性,并将其始终设置为UTC。这可能不适用于所有应用程序,但对我有用


1
投票

这里是解决方法的实现。让我知道您是否能找到更好的解决方案。谢谢!


1
投票

protobuf使用UtcKind自动反序列化DateTime可能更有意义,那样的话,如果您使用Utc作为基础,无论如何我都认为这是最佳实践,则不会有任何问题。


1
投票

假设您只需要一个[ProtoContract(SkipConstructor = true)] public class MyClass { [ProtoMember(3)] [XmlIgnore] private ProtoDateTime _timestampWrapper { get; set; } [ProtoIgnore] public DateTime Timestamp { get { return ProtoDateTime.getValue(ref _timestampWrapper); } set { return ProtoDateTime.setValue(out _timestampWrapper, value); } } [ProtoMember(4)] [XmlIgnore] private ProtoDateTime _nullableTimestampWrapper { get; set; } [ProtoIgnore] public DateTime? NullableTimestamp { get { return ProtoDateTime.getValueNullable(ref _nullableTimestampWrapper); } set { return ProtoDateTime.setValue(out _nullableTimestampWrapper, value); } } } (即DateTimeKindUTC),有一个简单的(虽然不是很漂亮的)解决方案。


1
投票

从protobuf-net 2.2(请参阅my blog开始),可以选择加入DateTime.Kind的序列化。您可以设置全局标志。 github上的相应commit(仍处于打开状态)。

© www.soinside.com 2019 - 2024. All rights reserved.