hooking into the deserialization process

自古美人都是妖i 提交于 2019-12-24 15:07:11

问题


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)
    {
    }

回答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.




回答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...




回答3:


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));
    }


来源:https://stackoverflow.com/questions/12692860/hooking-into-the-deserialization-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!