[This is a follow up on an older posting of mine, where I asked how to
control the object creation process when deserializing objects of a
certain class in order to ensure reference identity of these objects.
Alexander Shirshov told me to use IObjectReference, but I had already
solved the problem another way, somewhat awkwardly, but it worked.
Today, an e-mail reached me asking if I had actually solved the
problem using IObjectReference (which isn't so simple as I thought),
so I tried again and indeed found a solution.]

I found your posting in the advanced-dotnet site. I have run into exactly
the same problem as you. Therefore I ask you if you have found a
satisfactory solution. In all samples to IObjectReference they deserialise
to a singleton, which is not our case. We want to serialise the state
identifier only and deserialise to the typed constant, according to the
state identifier. So somehow, GetRealObject must get access to the state
identifier. But how? Did you solve the riddle?

Actually, I ended up using a serialization surrogate. However, after
reading your mail, I played around a little, and I found the following
solution, which uses the SerializationInfo passed to GetObjectData in
order to serialize state to be used by the serialization helper:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Diagnostics;

namespace Serialization {
   [Serializable]
   public sealed class Multiton : ISerializable {
       public enum Kind { Undefined, One, Two }

       public static Multiton Instance1 = new Multiton(Kind.One);
       public static Multiton Instance2 = new Multiton(Kind.Two);

       public readonly Kind MyKind;

       private Multiton(Kind kind) {
           this.MyKind = kind;
       }

       public void GetObjectData(SerializationInfo info,
StreamingContext context) {
           info.SetType(typeof(MultitonSerializationHelper));
           info.AddValue("kind", MyKind);
       }
   }

   [Serializable]
   class MultitonSerializationHelper : IObjectReference {
       public Multiton.Kind kind = Multiton.Kind.Undefined;

       public object GetRealObject(StreamingContext context) {
           switch (kind) {
               case Multiton.Kind.One:
                   return Multiton.Instance1;
               case Multiton.Kind.Two:
                   return Multiton.Instance2;
               default:
                   throw new Exception("object undefined!");
           }
       }
   }

   class Program {
       static void Main(string[] args) {
           BinaryFormatter formatter = new BinaryFormatter();
           byte[] data;

           using (MemoryStream stream = new MemoryStream()) {
               Multiton mta = Multiton.Instance1; // or Instance2
               formatter.Serialize(stream, mta);
               data = stream.GetBuffer();
           }

           using (MemoryStream stream = new MemoryStream(data)) {
               Multiton mtb = (Multiton)formatter.Deserialize(stream);
               Console.WriteLine(object.ReferenceEquals(mtb,
Multiton.Instance1));
               Console.WriteLine(object.ReferenceEquals(mtb,
Multiton.Instance2));
           }
       }
   }
}

Note that I've found that solution (using SerializationInfo for
storing state of the serialization helper) purely by experimentation -
it might be undocumented behavior.

Regards,
Fabian

PS: I'll also post this to the ADVANCED-DOTNET list for future reference.

===================================
This list is hosted by DevelopMentorĀ®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to