为了账号安全,请及时绑定邮箱和手机立即绑定

在 Linux 上反序列化 TimeZoneInfo 会抛出“月份参数必须在 1 到 12 范围内”

在 Linux 上反序列化 TimeZoneInfo 会抛出“月份参数必须在 1 到 12 范围内”

C#
GCT1015 2023-09-24 11:12:01
我正在将一个库从 .net Framework 4.7 迁移到 .net core 2.2,并发现了深度对象克隆的问题,我将其范围缩小到下面的一个简短的可重现代码片段。自己尝试一下:.net框架4.7.2(通过).net core 2.2(失败)using System;using System.IO;using System.Runtime.Serialization.Formatters.Binary;namespace Test{    public class Program    {        public static void Main(string[] args)        {            // any zone here, don't care what it is            var zone = TimeZoneInfo.GetSystemTimeZones()[0];                        var formatter = new BinaryFormatter();            using (MemoryStream stream = new MemoryStream())            {                formatter.Serialize(stream, zone);                stream.Seek(0, SeekOrigin.Begin);                var result = formatter.Deserialize(stream);                Console.WriteLine("all ok");            }        }    }}在使用 .net core 2.2 的 Windows 平台上,这工作正常,但在 Linux 平台上出现异常:Unhandled Exception: System.Runtime.Serialization.SerializationException: An error occurred while deserializing the object.  The serialized data is corrupt. ---> System.ArgumentOutOfRangeException: The Month parameter must be in the range 1 through 12.Parameter name: month   at System.TimeZoneInfo.TransitionTime.ValidateTransitionTime(DateTime timeOfDay, Int32 month, Int32 week, Int32 day, DayOfWeek dayOfWeek)   at System.TimeZoneInfo.TransitionTime.System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(Object sender)   --- End of inner exception stack trace ---   at System.TimeZoneInfo.TransitionTime.System.Runtime.Serialization.IDeserializationCallback.OnDeserialization(Object sender)   at System.Runtime.Serialization.ObjectManager.RaiseDeserializationEvent()问题:如何TimeZoneInfo在 Linux 中的 .net core 2.2 中使用二进制序列化?
查看完整描述

1 回答

?
梵蒂冈之花

TA贡献1900条经验 获得超5个赞

确实,这看起来像一个错误。

但是,从您的评论来看,似乎有一个简单的解决方法。不要序列化TimeZoneInfo,而是更改对象以仅序列化 ID。如果您愿意,您可以在其周围放置一个带有 get/set 访问器的属性,以方便使用。

例如,代替:

public class Foo

{

    public TimeZoneInfo TimeZone { get; set; }

}

你可以这样做:


public class Foo

{

    public string TimeZoneId { get; set; }


    public TimeZoneInfo TimeZone

    {

        get => TimeZoneInfo.FindSystemTimeZoneById(TimeZoneId);

        set => TimeZoneId = value.Id;

    }

}

唯一BinaryFormatter序列化字段,因此只有隐藏在自动属性后面的字符串TimeZoneId才会被序列化/反序列化。在序列化/反序列化期间将TimeZoneInfo被忽略,并且仅在您自己的代码中访问对象时使用。


查看完整回答
反对 回复 2023-09-24
  • 1 回答
  • 0 关注
  • 58 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信