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. BinaryFormatter: Serializing an object's base class

BinaryFormatter: Serializing an object's base class

Scheduled Pinned Locked Moved C#
question
29 Posts 7 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.
  • M mav northwind

    Well, the debugger shows "Animal {Dog}" as type for dogAsAnimal. a yields "Animal" and d yields "Dog", so I expected dogAsAnimal to be an Animal-type reference to an object that is Dog. It's the same with a direct cast. I cannot access the Dog-only properties of dogAsAnimal, but the BinaryFormatter seems to see through the cast and serialize the deepest inheritance.

    Regards, mav -- Black holes are the places where God divided by 0...

    M Offline
    M Offline
    Mark Salsbery
    wrote on last edited by
    #16

    What if you make the Dog class [Serializable], mark all its members [NonSerialized], and use a SerializationBinder[^] for deserialization? I'm not sure if it will work or not :)

    Mark Salsbery Microsoft MVP - Visual C++ :java:

    M 1 Reply Last reply
    0
    • M Mark Salsbery

      Ennis Ray Lynch, Jr. wrote:

      For standard XML serializaiton the default constructor needs to be public

      What if there's no default constructor?

      Ennis Ray Lynch, Jr. wrote:

      For binary serializaiton you need to have the serialization constructor defined.

      Not true. That's only for ISerializable-derived classes. ISerializable isn't required for binary serialization.

      Mark Salsbery Microsoft MVP - Visual C++ :java:

      E Offline
      E Offline
      Ennis Ray Lynch Jr
      wrote on last edited by
      #17

      I will believe you on the second one, however, a default constructor is defined by default unless you create either a non-default constructor or a default constructor with visibility other than public. See: http://support.microsoft.com/kb/330592[^]

      public class Foo{

      }

      and

      public class Foo{
      public Foo(){}
      }

      Both contain default constructors whereas

      public class Foo{
      public Foo(int a){}
      }

      and

      public class Foo{
      private Foo(){}
      }

      Do not.

      Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
      Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
      Most of this sig is for Google, not ego.

      M 2 Replies Last reply
      0
      • E Ennis Ray Lynch Jr

        I will believe you on the second one, however, a default constructor is defined by default unless you create either a non-default constructor or a default constructor with visibility other than public. See: http://support.microsoft.com/kb/330592[^]

        public class Foo{

        }

        and

        public class Foo{
        public Foo(){}
        }

        Both contain default constructors whereas

        public class Foo{
        public Foo(int a){}
        }

        and

        public class Foo{
        private Foo(){}
        }

        Do not.

        Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
        Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
        Most of this sig is for Google, not ego.

        M Offline
        M Offline
        Mark Salsbery
        wrote on last edited by
        #18

        Ennis Ray Lynch, Jr. wrote:

        a default constructor is defined by default unless you create either a non-default constructor or a default constructor with visibility other than public.

        Got it, thanks :) Mark

        Mark Salsbery Microsoft MVP - Visual C++ :java:

        1 Reply Last reply
        0
        • E Ennis Ray Lynch Jr

          I will believe you on the second one, however, a default constructor is defined by default unless you create either a non-default constructor or a default constructor with visibility other than public. See: http://support.microsoft.com/kb/330592[^]

          public class Foo{

          }

          and

          public class Foo{
          public Foo(){}
          }

          Both contain default constructors whereas

          public class Foo{
          public Foo(int a){}
          }

          and

          public class Foo{
          private Foo(){}
          }

          Do not.

          Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
          Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
          Most of this sig is for Google, not ego.

          M Offline
          M Offline
          Mark Salsbery
          wrote on last edited by
          #19

          Also, the constructor is only called when using XmlSerializer. No constructor is called with binary/SOAP deserialization. Cheers, Mark

          Mark Salsbery Microsoft MVP - Visual C++ :java:

          E 1 Reply Last reply
          0
          • M Mark Salsbery

            Also, the constructor is only called when using XmlSerializer. No constructor is called with binary/SOAP deserialization. Cheers, Mark

            Mark Salsbery Microsoft MVP - Visual C++ :java:

            E Offline
            E Offline
            Ennis Ray Lynch Jr
            wrote on last edited by
            #20

            I didn't know that, I just assumed a constructor would be called.

            Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
            Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
            Most of this sig is for Google, not ego.

            M 1 Reply Last reply
            0
            • M Mark Salsbery

              What if you make the Dog class [Serializable], mark all its members [NonSerialized], and use a SerializationBinder[^] for deserialization? I'm not sure if it will work or not :)

              Mark Salsbery Microsoft MVP - Visual C++ :java:

              M Offline
              M Offline
              mav northwind
              wrote on last edited by
              #21

              Thanks for the suggestion, I'll take a look. Jeez, I didn't expect it to get so complicated... ;P

              Regards, mav -- Black holes are the places where God divided by 0...

              M 2 Replies Last reply
              0
              • E Ennis Ray Lynch Jr

                I didn't know that, I just assumed a constructor would be called.

                Need software developed? Offering C# development all over the United States, ERL GLOBAL, Inc is the only call you will have to make.
                Happiness in intelligent people is the rarest thing I know. -- Ernest Hemingway
                Most of this sig is for Google, not ego.

                M Offline
                M Offline
                Mark Salsbery
                wrote on last edited by
                #22

                I was trying to convince myself more than you I think :) I knew I read it somewhere once, and testing confirmed it. Its obscurely "documented" here[^]. I appreciate the discussion, thanks! Mark

                Mark Salsbery Microsoft MVP - Visual C++ :java:

                1 Reply Last reply
                0
                • M mav northwind

                  Thanks for the suggestion, I'll take a look. Jeez, I didn't expect it to get so complicated... ;P

                  Regards, mav -- Black holes are the places where God divided by 0...

                  M Offline
                  M Offline
                  Mark Salsbery
                  wrote on last edited by
                  #23

                  I was bored, so I tried it. Works great :)

                  \[Serializable\]
                  public class Animal
                  {
                  	public string str
                  	{
                  		get;
                  		set;
                  	}
                  }
                  
                  \[Serializable\]
                  public class Dog : Animal
                  {
                  	\[NonSerialized\]  `//<-- Optional!`
                  	public Int32 A;
                  
                  	\[NonSerialized\]  `//<-- Optional!`
                  	public Int32 B;
                  
                  	public Dog()
                  	{
                  		A = 5;
                  		B = 10;
                  	}
                  }
                  
                  sealed class DogToAnimalDeserializationBinder : SerializationBinder
                  {
                  	public override Type BindToType(string assemblyName, string typeName)
                  	{
                  		Type typeToDeserialize = null;
                  
                  		String assemVer1 = Assembly.GetExecutingAssembly().FullName;
                  		String typeVer1 = "Dog";
                  
                  		if (assemblyName == assemVer1 && typeName == typeVer1)
                  		{
                  			typeName = "Animal";
                  		}
                  
                  		// The following line of code returns the type.
                  		typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
                  			typeName, assemblyName));
                  
                  		return typeToDeserialize;
                  	}
                  }
                  

                  ...

                  Dog dog = new Dog();
                  dog.A = 3;
                  dog.B = 5;
                  dog.str = "Animal String";

                  MemoryStream MemStream = new MemoryStream();

                  // Serialize a Dog object
                  BinaryFormatter Serializer = new BinaryFormatter();
                  Serializer.Serialize(MemStream, dog);

                  MemStream.Seek(0, SeekOrigin.Begin);

                  // Deserialize as an Animal object
                  Serializer.Binder = new DogToAnimalDeserializationBinder();
                  Animal animal = (Animal)Serializer.Deserialize(MemStream);

                  Mark Salsbery Microsoft MVP - Visual C++ :java:

                  1 Reply Last reply
                  0
                  • M mav northwind

                    Thanks for the suggestion, I'll take a look. Jeez, I didn't expect it to get so complicated... ;P

                    Regards, mav -- Black holes are the places where God divided by 0...

                    M Offline
                    M Offline
                    Mark Salsbery
                    wrote on last edited by
                    #24

                    Wow - my code was overcomplicated. The Binder there is completely unnecessary :rolleyes:

                    mav.northwind wrote:

                    The other side of the line (where the object is supposed to be deserialized) doesn't know about Dogs, it only knows about Animals (i.e. there's only the assembly defining Animal available, not the one defining Dog, so trying to deserialize this object will throw a TypeLoadException).

                    I just noticed that post. The only way that's going to work is to serialize an Animal object in the first place, as you already know. The deserializing end could use a custom binder to deserialize a Dog, but that would still require that end to have the assembly implementing the Dog class. Basically I helped get you back where you started, sorry! :)

                    Mark Salsbery Microsoft MVP - Visual C++ :java:

                    M 1 Reply Last reply
                    0
                    • M Mark Salsbery

                      Wow - my code was overcomplicated. The Binder there is completely unnecessary :rolleyes:

                      mav.northwind wrote:

                      The other side of the line (where the object is supposed to be deserialized) doesn't know about Dogs, it only knows about Animals (i.e. there's only the assembly defining Animal available, not the one defining Dog, so trying to deserialize this object will throw a TypeLoadException).

                      I just noticed that post. The only way that's going to work is to serialize an Animal object in the first place, as you already know. The deserializing end could use a custom binder to deserialize a Dog, but that would still require that end to have the assembly implementing the Dog class. Basically I helped get you back where you started, sorry! :)

                      Mark Salsbery Microsoft MVP - Visual C++ :java:

                      M Offline
                      M Offline
                      mav northwind
                      wrote on last edited by
                      #25

                      Hmmm, I've played around with the SerializationBinder a bit, but didn't get a useable result either. If I always return typeof(Animal) as target type in BindToType, then the deserializing end doesn't require knowledge about Dog, but unfortunately it doesn't work because then even Animal's properties aren't deserialized if I have a Dog object in my serialization stream. :(

                      Regards, mav -- Black holes are the places where God divided by 0...

                      M 1 Reply Last reply
                      0
                      • G Giorgi Dalakishvili

                        See if this helps: Advanced Binary Serialization: Deserializing an Object Into a Different Type Than the One It was Serialized Into[^]

                        Giorgi Dalakishvili #region signature My Articles / My Latest Article[^] / My blog[^] #endregion

                        M Offline
                        M Offline
                        mav northwind
                        wrote on last edited by
                        #26

                        Thanks for the link, it was quite instructive, although I couldn't achieve useable results so far with a SerializationBinder... Nevertheless: thanks for taking your time.

                        Regards, mav -- Black holes are the places where God divided by 0...

                        1 Reply Last reply
                        0
                        • M mav northwind

                          Hmmm, I've played around with the SerializationBinder a bit, but didn't get a useable result either. If I always return typeof(Animal) as target type in BindToType, then the deserializing end doesn't require knowledge about Dog, but unfortunately it doesn't work because then even Animal's properties aren't deserialized if I have a Dog object in my serialization stream. :(

                          Regards, mav -- Black holes are the places where God divided by 0...

                          M Offline
                          M Offline
                          Mark Salsbery
                          wrote on last edited by
                          #27

                          Right. The only way I can see to do it, if the deserialization end has no access to the Dog class (or an equivalent class), is to add a method to Dog that returns an Animal object and serialize that object. It's really unconventional anyway....it generally doesn't make sense to only serialize the base class portion of an object. But if you have a special need I suppose you need a special solution. :) Mark

                          Mark Salsbery Microsoft MVP - Visual C++ :java:

                          M 1 Reply Last reply
                          0
                          • M Mark Salsbery

                            Right. The only way I can see to do it, if the deserialization end has no access to the Dog class (or an equivalent class), is to add a method to Dog that returns an Animal object and serialize that object. It's really unconventional anyway....it generally doesn't make sense to only serialize the base class portion of an object. But if you have a special need I suppose you need a special solution. :) Mark

                            Mark Salsbery Microsoft MVP - Visual C++ :java:

                            M Offline
                            M Offline
                            mav northwind
                            wrote on last edited by
                            #28

                            I think I got it! After your and Giorgi's hints concerning the SerializationBinder, I looked at BinaryFormatter's other properties and found SurrogateSelector and subsequently ISerializationSurrogate. Using these two interfaces I was able to control the serialization process in a way that only Animal's properties are being serialized and during deserialization a real Animal object is being created. This should do the trick... Thanks for taking your time!

                            Regards, mav -- Black holes are the places where God divided by 0...

                            M 1 Reply Last reply
                            0
                            • M mav northwind

                              I think I got it! After your and Giorgi's hints concerning the SerializationBinder, I looked at BinaryFormatter's other properties and found SurrogateSelector and subsequently ISerializationSurrogate. Using these two interfaces I was able to control the serialization process in a way that only Animal's properties are being serialized and during deserialization a real Animal object is being created. This should do the trick... Thanks for taking your time!

                              Regards, mav -- Black holes are the places where God divided by 0...

                              M Offline
                              M Offline
                              Mark Salsbery
                              wrote on last edited by
                              #29

                              Very cool! Thanks for the update! Cheers, Mark

                              Mark Salsbery Microsoft MVP - Visual C++ :java:

                              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