Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C#
  4. Serialization problem

Serialization problem

Scheduled Pinned Locked Moved C#
graphicsjsonhelptutorialannouncement
7 Posts 3 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Alan Balkany
    wrote on last edited by
    #1

    I'm having a hard time deserializing old versions of a class after adding a new member. I've written a toy program that's the simplest possible example of this problem. Maybe someone else might notice what I'm doing wrong. I have a class with one member: A System.Drawing.Color:

    \[Serializable\]
    public class SerialObj
    {
        public System.Drawing.Color color;
    }
    

    The following code serializes/deserializes it with no problem:

            SoapFormatter formatter = new SoapFormatter();     // Serialize:
            formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
            formatter.Serialize(myStream, so);
    
            SoapFormatter formatter = new SoapFormatter();     // Deserialize:
            formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
            so = (SerialObj)formatter.Deserialize(myStream);
    

    I added an int member, and I'm trying to use the ISerializable interface to handle the different versions. This interface requires a constructor with two special parameters, and a GetObjectData method:

    \[Serializable\]
    public class SerialObj : ISerializable
    {
        public System.Drawing.Color color;
        public int number;                   // The new member.
    
        public SerialObj()
        {
            System.Windows.Forms.MessageBox.Show("In empty ctor.");
        }
    
    
        public SerialObj(SerializationInfo info, StreamingContext cntxt)
        {
            System.Windows.Forms.MessageBox.Show("In full ctor.");
            color = (System.Drawing.Color)info.GetValue("color", typeof(System.Drawing.Color));
    
            try
            {
                number = info.GetInt32("number");
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }
        }
    
    
        void ISerializable.GetObjectData(SerializationInfo inf, StreamingContext cxt)
        {
            System.Windows.Forms.MessageBox.Show("In GetObjectData.");
            inf.AddValue("color", color);
            inf.AddValue("number", number);
        }
    }
    

    It works for serialized new versions with both members. But when I deserialize an old version (without the int), it crashes on the Deserialize call, with the exception: "Top Object cannot be instantiated for element 'color'." It never even calls either constructor. Can

    M L 2 Replies Last reply
    0
    • A Alan Balkany

      I'm having a hard time deserializing old versions of a class after adding a new member. I've written a toy program that's the simplest possible example of this problem. Maybe someone else might notice what I'm doing wrong. I have a class with one member: A System.Drawing.Color:

      \[Serializable\]
      public class SerialObj
      {
          public System.Drawing.Color color;
      }
      

      The following code serializes/deserializes it with no problem:

              SoapFormatter formatter = new SoapFormatter();     // Serialize:
              formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
              formatter.Serialize(myStream, so);
      
              SoapFormatter formatter = new SoapFormatter();     // Deserialize:
              formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
              so = (SerialObj)formatter.Deserialize(myStream);
      

      I added an int member, and I'm trying to use the ISerializable interface to handle the different versions. This interface requires a constructor with two special parameters, and a GetObjectData method:

      \[Serializable\]
      public class SerialObj : ISerializable
      {
          public System.Drawing.Color color;
          public int number;                   // The new member.
      
          public SerialObj()
          {
              System.Windows.Forms.MessageBox.Show("In empty ctor.");
          }
      
      
          public SerialObj(SerializationInfo info, StreamingContext cntxt)
          {
              System.Windows.Forms.MessageBox.Show("In full ctor.");
              color = (System.Drawing.Color)info.GetValue("color", typeof(System.Drawing.Color));
      
              try
              {
                  number = info.GetInt32("number");
              }
              catch (Exception ex)
              {
                  System.Windows.Forms.MessageBox.Show(ex.Message);
              }
          }
      
      
          void ISerializable.GetObjectData(SerializationInfo inf, StreamingContext cxt)
          {
              System.Windows.Forms.MessageBox.Show("In GetObjectData.");
              inf.AddValue("color", color);
              inf.AddValue("number", number);
          }
      }
      

      It works for serialized new versions with both members. But when I deserialize an old version (without the int), it crashes on the Deserialize call, with the exception: "Top Object cannot be instantiated for element 'color'." It never even calls either constructor. Can

      M Offline
      M Offline
      Migounette
      wrote on last edited by
      #2

      Try this.... // Version 1.0 [Serializable] public class SerialObj { public System.Drawing.Color color; } // Version 2.0 [Serializable] public class SerialObj { public System.Drawing.Color color; [OptionalField(VersionAdded = 2)] public int number; } // Version 3.0 [Serializable] public class SerialObj { public System.Drawing.Color color; [OptionalField(VersionAdded=2)] public int number; [OptionalField(VersionAdded=3)] public int solution; }

      A 2 Replies Last reply
      0
      • M Migounette

        Try this.... // Version 1.0 [Serializable] public class SerialObj { public System.Drawing.Color color; } // Version 2.0 [Serializable] public class SerialObj { public System.Drawing.Color color; [OptionalField(VersionAdded = 2)] public int number; } // Version 3.0 [Serializable] public class SerialObj { public System.Drawing.Color color; [OptionalField(VersionAdded=2)] public int number; [OptionalField(VersionAdded=3)] public int solution; }

        A Offline
        A Offline
        Alan Balkany
        wrote on last edited by
        #3

        Thanks for the suggestion, but according to this (http://msdn.microsoft.com/en-us/library/ms229752.aspx[^]) the OptionalField attribute doesn't work with the SoapFormatter (just the BinaryFormatter). Versions have been released using the SoapFormatter, so I can't change it at this point.

        1 Reply Last reply
        0
        • A Alan Balkany

          I'm having a hard time deserializing old versions of a class after adding a new member. I've written a toy program that's the simplest possible example of this problem. Maybe someone else might notice what I'm doing wrong. I have a class with one member: A System.Drawing.Color:

          \[Serializable\]
          public class SerialObj
          {
              public System.Drawing.Color color;
          }
          

          The following code serializes/deserializes it with no problem:

                  SoapFormatter formatter = new SoapFormatter();     // Serialize:
                  formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
                  formatter.Serialize(myStream, so);
          
                  SoapFormatter formatter = new SoapFormatter();     // Deserialize:
                  formatter.AssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
                  so = (SerialObj)formatter.Deserialize(myStream);
          

          I added an int member, and I'm trying to use the ISerializable interface to handle the different versions. This interface requires a constructor with two special parameters, and a GetObjectData method:

          \[Serializable\]
          public class SerialObj : ISerializable
          {
              public System.Drawing.Color color;
              public int number;                   // The new member.
          
              public SerialObj()
              {
                  System.Windows.Forms.MessageBox.Show("In empty ctor.");
              }
          
          
              public SerialObj(SerializationInfo info, StreamingContext cntxt)
              {
                  System.Windows.Forms.MessageBox.Show("In full ctor.");
                  color = (System.Drawing.Color)info.GetValue("color", typeof(System.Drawing.Color));
          
                  try
                  {
                      number = info.GetInt32("number");
                  }
                  catch (Exception ex)
                  {
                      System.Windows.Forms.MessageBox.Show(ex.Message);
                  }
              }
          
          
              void ISerializable.GetObjectData(SerializationInfo inf, StreamingContext cxt)
              {
                  System.Windows.Forms.MessageBox.Show("In GetObjectData.");
                  inf.AddValue("color", color);
                  inf.AddValue("number", number);
              }
          }
          

          It works for serialized new versions with both members. But when I deserialize an old version (without the int), it crashes on the Deserialize call, with the exception: "Top Object cannot be instantiated for element 'color'." It never even calls either constructor. Can

          L Offline
          L Offline
          Luc Pattyn
          wrote on last edited by
          #4

          Hi Alan, I haven't studied the subject yet, however it so happens I just read a CP thread about this, and it seems you need to use SerializationBinder class. MSDN even holds an example. :)

          Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


          Getting an article published on CodeProject should be easier and faster for Bronze and Silver authors.


          A 1 Reply Last reply
          0
          • L Luc Pattyn

            Hi Alan, I haven't studied the subject yet, however it so happens I just read a CP thread about this, and it seems you need to use SerializationBinder class. MSDN even holds an example. :)

            Luc Pattyn [Forum Guidelines] [Why QA sucks] [My Articles]


            Getting an article published on CodeProject should be easier and faster for Bronze and Silver authors.


            A Offline
            A Offline
            Alan Balkany
            wrote on last edited by
            #5

            Thanks Luc. I have tried using a custom SerializationBinder (for the formatter.Binder member). It implements a single method, BindToType, which appears to be used repeatedly as a subroutine for the .NET framework serialization, that returns a Type when given a typeName string. It didn't avoid the error message I'm getting. The error happens after the return from the Binder, with the type that had the added member.

            1 Reply Last reply
            0
            • M Migounette

              Try this.... // Version 1.0 [Serializable] public class SerialObj { public System.Drawing.Color color; } // Version 2.0 [Serializable] public class SerialObj { public System.Drawing.Color color; [OptionalField(VersionAdded = 2)] public int number; } // Version 3.0 [Serializable] public class SerialObj { public System.Drawing.Color color; [OptionalField(VersionAdded=2)] public int number; [OptionalField(VersionAdded=3)] public int solution; }

              A Offline
              A Offline
              Alan Balkany
              wrote on last edited by
              #6

              Migounette, I tried your suggestion anyway, and it works with the new versions (both members), but not with the old versions (color member only). The error message is: "Member at position 0 was null. Parameter name: members". I don't have any variable named "members", so it must be referring to something internal to .NET.

              M 1 Reply Last reply
              0
              • A Alan Balkany

                Migounette, I tried your suggestion anyway, and it works with the new versions (both members), but not with the old versions (color member only). The error message is: "Member at position 0 was null. Parameter name: members". I don't have any variable named "members", so it must be referring to something internal to .NET.

                M Offline
                M Offline
                Migounette
                wrote on last edited by
                #7

                Not sure about the error Members of what ? Try this: public int number { get; set; } or I was looking at SOAP (never played with), but maybe with the extension of the attribute for soap envelop may work. http://msdn.microsoft.com/en-us/library/system.xml.serialization.soapignoreattribute.aspx[^] Good luck :)

                1 Reply Last reply
                0
                Reply
                • Reply as topic
                Log in to reply
                • Oldest to Newest
                • Newest to Oldest
                • Most Votes


                • Login

                • Don't have an account? Register

                • Login or register to search.
                • First post
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • World
                • Users
                • Groups