1

I have a DateRange object that represents the notion of Infinity via Static reference as shown below. As you see, the end points that define Infinity are also static references in a different class, DatePoint.Past and DatePoint.Future.

Now I need to serialize this (as part of a deep Clone method that uses serialization) and know when it's deserialized that an instance with DateTime.Min and DateTime.Max as endpoints then the instance should be DateRange.Infinity. So I think I need to make it ISerializable.

My first attempt at implementing ISerializable is quite poor; and but I'm showing it in the hopes it suggests a quicker fix to someone. I have used some similar code for NHibernate to store DateRange in the db and reconstitue Infinity, but I'm not getting how to apply that for serialization yet.

DatePoint is marked [Serializable] but does not implement ISerializable.

edited question

I am not looking to serialize/deserialize Infinity. What I am looking for is a hook into where I can take the deserialized DataRange and decide if it is equivalent to Infinity.

**

Cheers, Berryl

DateRange

[Serializable]
[TypeConverter(typeof(DateRangeTypeConverter))]
public class DateRange : ValueObject, IRange<DatePoint, DateRange, TimeSpan>, ISerializable
{
    /// <summary>
    /// Returns a range spanning <see cref="DatePoint.Past"/> and <see cref="DatePoint.Future"/>.
    /// </summary>
    public static readonly DateRange Infinity = new DateRange(DatePoint.Past, DatePoint.Future);


    /// <summary> The start of the <see cref="DateRange"/> range. </summary>
    public DatePoint Start { get; protected set; }

    /// <summary> The end of the <see cref="DateRange"/> range. </summary>
    public DatePoint End { get; protected set; }

}

DatePoint

public class DatePoint : ValueObject, IComparable<DatePoint>, IComparable<DateTime>, IComparable, IEquatable<DatePoint>, IEquatable<DateTime>, IFormattable
{

    /// <summary>The undefined infinite past, smaller than any other date except itself.</summary>
    public readonly static DatePoint Past = DateTime.MinValue;

    /// <summary>The undefined infinite future, larger than any other date except itself.</summary>
    public readonly static DatePoint Future = DateTime.MaxValue;

}

First ISerializable attempt

    protected DateRange(SerializationInfo info, StreamingContext ctx) {
        if (info == null)
            throw new System.ArgumentNullException("info");
        var start = (DatePoint)info.GetValue("Start", typeof(DatePoint));
        var end = (DatePoint)info.GetValue("End", typeof(DatePoint));
        // its Infinity if so
        if((start.Equals(DatePoint.Past) && end.Equals(DatePoint.Future)))
            return;
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
    }
Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193
Berryl
  • 12,471
  • 22
  • 98
  • 182
  • possible duplicate of [Does "default" serialization in C# serialize static fields?](http://stackoverflow.com/questions/3903079/does-default-serialization-in-c-sharp-serialize-static-fields) – L.B Oct 02 '12 at 15:07
  • @L.B. It is related to that question but not the same. I am looking for a work around to deal with it. MS has a [static helper class here](http://msdn.microsoft.com/query/dev10.query?appId=Dev10IDEF1&l=EN-US&k=k(SYSTEM.RUNTIME.SERIALIZATION.SERIALIZATIONINFO);k(SERIALIZATIONINFO);k(SOLUTIONITEMSPROJECT);k(SOLUTIONITEMSPROJECT);k(TargetFrameworkMoniker-%22.NETFRAMEWORK%2cVERSION%3dV4.0%22);k(DevLang-CSHARP)&rd=true) so am assuming it is possible. Cheers – Berryl Oct 02 '12 at 15:16
  • @everyone: The question asked here is not about serializing a static field. – Stefan Steinegger Oct 03 '12 at 13:59

3 Answers3

2

You cannot create an instance of a static member, and therefore they cannot be serialized or deserialized.

You may instead create a proper public property with a protected set which doesn't do anything and a get which returns the result you want. The property can then be serialized, but not deserialized because that would be an exercise in futility...

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76
  • If I did it with a property as you suggest would that make implementing ISerializable unnecessary? Can you scratch out some quick and dirty code? – Berryl Oct 02 '12 at 15:13
  • Why do you need to serialize it anyway? It's a function rather than a property/field, really, isn't it? – Roy Dictus Oct 02 '12 at 15:18
  • DateRange will be a property of other classes that need to be serialized. I don't care about serializing the static field at all, I care about knowing that a deserialized DateRange is Infinity, and not DateTime.Min to DateTime.Max. Does this make sense? – Berryl Oct 02 '12 at 15:22
  • @Roy: The question asked here is not about serializing a static field. – Stefan Steinegger Oct 03 '12 at 14:00
1

You can implement IObjectReference and replace the object after deserialization:

object IObjectReference.GetRealObject(StreamingContext context)
{
    if (Start.Equals(DatePoint.Past) && End.Equals(DatePoint.Future))
    {
        return Infinity;
    }
}

See the documentation.

Stefan Steinegger
  • 63,782
  • 15
  • 129
  • 193
  • Love this, and am marking this as the answer since it's the cleanest answer to what I asked. There is actually an implementation detail in my DateRange where DatePoint.Future differs from DateTime.Max by a second, and there are some other open ended DateRanges besides Infinity; so am sticking with the answer I wrote below. – Berryl Oct 03 '12 at 19:25
  • 1
    What you do is marking the infinity in the serialized data. I don't understand why you do that, because you should be able to compare the values when you deserialize. You can have this more easily: add a field "isInfinity" that is set in the constructor, and only the Infinity instance sets it to true. When it is true, you can replace the instance after deserialization the way I do. – Stefan Steinegger Oct 04 '12 at 05:33
0

I do NOT like answering my own question, but here is a solution that seems to work. Probably I just didn't ask the question right in the first place, and I didn't know how to do the below when I asked it.

Someone sees a better way to do it, please say so!

Cheers,
Berryl

Make DateRange implement ISerializable

    protected DateRange(SerializationInfo info, StreamingContext context) {
        if (info == null)
            throw new ArgumentNullException("info");

        var foundPast = (bool) info.GetValue("thePast", typeof (bool));
        if (foundPast)
            Start = DatePoint.Past;
        var foundFuture = (bool) info.GetValue("theFuture", typeof (bool));
        if (foundFuture)
            End = DatePoint.Future;
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("thePast", Start.Equals(DatePoint.Past), typeof(bool));
        info.AddValue("theFuture", End.Equals(DatePoint.Future), typeof(bool));
    }
Berryl
  • 12,471
  • 22
  • 98
  • 182