From 850bae031cea3d3923bdf280c7080dc36d9cea1c Mon Sep 17 00:00:00 2001 From: Miguel de Icaza Date: Fri, 16 Mar 2007 16:26:31 +0000 Subject: [PATCH] 2007-03-16 Lionel Cuir * DateTime.cs: Added support in 2.0 for Serialization. svn path=/trunk/mcs/; revision=74469 --- mcs/class/corlib/System/ChangeLog | 4 + mcs/class/corlib/System/DateTime.cs | 126 +++++++++++++++++++++++++++- 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/mcs/class/corlib/System/ChangeLog b/mcs/class/corlib/System/ChangeLog index 760cc46ae4ef8..be5c52bede206 100644 --- a/mcs/class/corlib/System/ChangeLog +++ b/mcs/class/corlib/System/ChangeLog @@ -1,3 +1,7 @@ +2007-03-16 Lionel Cuir + + * DateTime.cs: Added support in 2.0 for Serialization. + 2007-03-11 Gert Driesen * Delegate.cs: Fixed bootstrap build. diff --git a/mcs/class/corlib/System/DateTime.cs b/mcs/class/corlib/System/DateTime.cs index fa7cadce726eb..cf71cab272e6a 100644 --- a/mcs/class/corlib/System/DateTime.cs +++ b/mcs/class/corlib/System/DateTime.cs @@ -33,6 +33,7 @@ using System.Globalization; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Serialization; using System.Text; namespace System @@ -46,7 +47,7 @@ namespace System [StructLayout (LayoutKind.Auto)] public struct DateTime : IFormattable, IConvertible, IComparable #if NET_2_0 - , IComparable, IEquatable + , IComparable, IEquatable, ISerializable #endif { private TimeSpan ticks; @@ -2149,5 +2150,128 @@ UInt64 IConvertible.ToUInt64(IFormatProvider provider) { throw new InvalidCastException(); } + +#if NET_2_0 // ISerializable Members + + private DateTime(SerializationInfo info, StreamingContext context) + { + this.kind = DateTimeKind.Unspecified; + this.ticks = TimeSpan.MinValue; + + if (info == null) + throw new ArgumentNullException("info"); + + /* + * Mono and .Net have different 'signatures' for their SerializationInfo's content: + * + * Mono uses: + * - ticks, a TimeSpan + * - kind, a DateTimeKind (only on .NET 2.0) + * + * And .Net uses: + * - in v1.0: ???? + * - in v1.1: ticks, a long + * - in v2.0: ticks (a long) and dateData (a ulong) with the first end being the kind and the right end the ticks + * + * So we first enumerate the available field names & types, and then decide what to do on that basis. + * If the kind is not present, it shoud be considered as equal to 0 (Unspecified). + */ + + SerializationInfoEnumerator serializedFieldEnum = info.GetEnumerator(); + int fieldCount = info.MemberCount; + string serializedFieldName; + Type serializedFieldType; + + if (fieldCount == 1) + { + #region This DateTime should have been serialized under the .NET framework 1.x or with Mono for framework v1.x + serializedFieldName = serializedFieldEnum.Name; + serializedFieldType = serializedFieldEnum.ObjectType; + if (serializedFieldName != "ticks") + throw new SerializationException("Invalid serialized data for this DataTime - 1 single unknown member."); + + if (serializedFieldType == typeof(TimeSpan)) + { + // This is a DateTime serialized under Mono for framework 1.x + this.ticks = (TimeSpan)serializedFieldEnum.Value; + } + else if(serializedFieldType == typeof(long)) + { + // This is a DateTime serialized under .NET 1.x + this.ticks = new TimeSpan((long)serializedFieldEnum.Value); + } + else + throw new SerializationException("Invalid serialized data for this DataTime - member 'ticks' not of the expected types."); + #endregion This DateTime should have been serialized under the .NET framework 1.x or with Mono for framework v1.x + } + else if (fieldCount == 2) + { + #region This DateTime should have been serialized under .Net 2.x or under Mono for the framework v2.x. + bool isMono = false; + + serializedFieldEnum.MoveNext(); + serializedFieldName = serializedFieldEnum.Name; + serializedFieldType = serializedFieldEnum.ObjectType; + + if (serializedFieldName != "ticks") + throw new SerializationException("Missing ticks field in a DateTime serialized with .NET or Mono for the version 2.x but it isn't"); + + if (serializedFieldType == typeof(long)) + { + isMono = false; + this.ticks = new TimeSpan((long)serializedFieldEnum.Value); + } + else if (serializedFieldType == typeof(TimeSpan)) + { + isMono = true; + this.ticks = (TimeSpan)serializedFieldEnum.Value; + } + else + throw new SerializationException("Unknown ticks field type in a DateTime serialized with .NET or Mono for the version 2.x"); + + + serializedFieldEnum.MoveNext(); + serializedFieldName = serializedFieldEnum.Name; + serializedFieldType = serializedFieldEnum.ObjectType; + if (!isMono && serializedFieldName == "dateData" && serializedFieldType == typeof(ulong)) + { + ulong dateData = (ulong)serializedFieldEnum.Value; + ulong leftpart = dateData & 0xc000000000000000; + // If we do nothing, we let kind = 0 (ie Unspecified) + if (leftpart == 0) + this.kind = DateTimeKind.Unspecified; + else if (leftpart == 0x4000000000000000) + this.kind = DateTimeKind.Utc; + else + this.kind = DateTimeKind.Local; + } + else if(isMono && serializedFieldName == "kind" && serializedFieldType == typeof(DateTimeKind)) + { + this.kind = (DateTimeKind)serializedFieldEnum.Value; + } + else + throw new SerializationException("This should be a DateTime serialized with .NET or Mono for the version 2.x but it isn't"); + + #endregion This DateTime should have been serialized under .Net 2.x or under Mono for the framework v2.x. + } + else + throw new SerializationException("Invalid serialized data for this DataTime - (3 members or more)."); + } + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new System.ArgumentNullException("info"); + + info.AddValue("ticks", this.ticks.Ticks); + + // We serialize the DateTime the .Net 2.x way. + // Let's store the kind into the left part of dateData, and the ticks into the right part. + ulong dateData = (ulong) ((((long) kind) << 0x3e) | ticks.Ticks); + + info.AddValue("dateData", dateData); + } + +#endif } }