Skip to content

Commit

Permalink
2007-03-16 Lionel Cuir <lionel_email@aulofee.com>
Browse files Browse the repository at this point in the history
	* DateTime.cs: Added support in 2.0 for Serialization. 

svn path=/trunk/mcs/; revision=74469
  • Loading branch information
migueldeicaza committed Mar 16, 2007
1 parent ec1a2da commit 850bae0
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 1 deletion.
4 changes: 4 additions & 0 deletions mcs/class/corlib/System/ChangeLog
@@ -1,3 +1,7 @@
2007-03-16 Lionel Cuir <lionel_email@aulofee.com>

* DateTime.cs: Added support in 2.0 for Serialization.

2007-03-11 Gert Driesen <drieseng@users.sourceforge.net>

* Delegate.cs: Fixed bootstrap build.
Expand Down
126 changes: 125 additions & 1 deletion mcs/class/corlib/System/DateTime.cs
Expand Up @@ -33,6 +33,7 @@
using System.Globalization;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Text;

namespace System
Expand All @@ -46,7 +47,7 @@ namespace System
[StructLayout (LayoutKind.Auto)]
public struct DateTime : IFormattable, IConvertible, IComparable
#if NET_2_0
, IComparable<DateTime>, IEquatable <DateTime>
, IComparable<DateTime>, IEquatable<DateTime>, ISerializable
#endif
{
private TimeSpan ticks;
Expand Down Expand Up @@ -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
}
}

0 comments on commit 850bae0

Please sign in to comment.