1 Reply Latest reply on Sep 7, 2009 10:12 PM by Flex harUI

    How should I initialize while deserializing objects?

    WebSnozz

      I have created the below application as a very simplified example of my problem.  I have an opbject graph which essentially is a data model which I serialize to a file on application close, and deserialize on application open to save and restore the application's state. Since there is a root object, in the below example this would be mClassA, I simply serialize and deserialize that object, and all the containing objects are also saved.  The problem I have is that during deserialization, each objects default constructor is called, which causes contained objects to also be created, when those contained objects actually will be deserialized.  So for example, running the below application would produce the following output whenever the file is deserialized:

      ClassA.ClassA()  //ClassA is created by WindowedApplication
      ClassB.ClassB()  //ClassA creates ClassB
      ClassC.ClassC()  //ClassB creates ClassC
      ClassA.ClassA()  //+ClassA's default constructor is called when deserialized in WindowedApplication.init()
      ClassB.ClassB()  //ClassA(the one just deserialized) creates ClassB
      ClassC.ClassC()  //ClassB creates ClassC
      ClassB.ClassB()  //+ClassB's default constructor is also called by the same deserialization
      ClassC.ClassC()  //ClassC is created by the new ClassB
      ClassC.ClassC()  //+ClassC's default constructor is called while being deserilized

       

      I marked the class instances that really matter, the one's created from ReadObject, with a +.  After a Class is deserilized, it is assigned(by the deserialization process) to classes which refernced it.  For example one the last classC is deserilized, it is then assigned to ClassB.classC.

      So in this case 4 instances of a ClassC are created, when the only one we really cared or wanted is the last one that was deserilized.

       

      So how can I ensure I don't initialize a contained property, if it is going to be set by the deserilizer?  I.E. skip creating and setting properties if the class is actually being deserialized, because it will get initialized by the deserialization process.

       

       

       

          [RemoteClass]
          [Bindable]
          public class ClassA
          {
             
              public var classB:ClassB;
             
              public function ClassA()
              {
                  trace("ClassA.ClassA()");

                  //I want to skip creating a new ClassB if we are going to deserialize one
                  classB = new ClassB();           
              }
          }

       

          [RemoteClass]
          [Bindable]
          public class ClassB
          {
              public var classC:ClassC;
             
              public function ClassB()
              {
                  trace("ClassB.ClassB()");
                 
                  classC = new ClassC();
              }

          }

       

          [RemoteClass]
          [Bindable]
          public class ClassC
          {
              public function ClassC()
              {
                  trace("ClassC.ClassC()");
              }
          }

       

      <?xml version="1.0" encoding="utf-8"?>
      <mx:WindowedApplication xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
          initialize="init()" closing="onWindowClosing(event)">
          <mx:Script>
              <![CDATA[
                  private var mClassA:ClassA = new ClassA();
             
                  private function onWindowClosing(event:Event):void
                  {
                      writeObjectToFile(mClassA,"classA.dat");
                  }
                 
                  private function init():void
                  {
                      var classA:ClassA = null;
                      if(classA = (readObjectFromFile("classA.dat") as ClassA))
                      {
                          //if we found a file and were able
                          //to deserialize a ClassA, then use it:
                          mClassA = classA;
                      }
                  }
                 
                   public static function writeObjectToFile(object:Object, fname:String):void
                  {
                    var file:File = File.applicationStorageDirectory.resolvePath(fname);
             
                    var fileStream:FileStream = new FileStream();
                    fileStream.open(file, FileMode.WRITE);
                    fileStream.writeObject(object);
                    fileStream.close();
                  }
                
                  public static function readObjectFromFile(fname:String):Object
                  {
                    var file:File = File.applicationStorageDirectory.resolvePath(fname);
             
                    if(file.exists) {
                      var obj:Object;
                      var fileStream:FileStream = new FileStream();
                      fileStream.open(file, FileMode.READ);
                      obj = fileStream.readObject();
                      fileStream.close();
                      return obj;
                    }
                    return null;
                  }
              ]]>
          </mx:Script>
      </mx:WindowedApplication>