[.net] Abandoning .net serialization?

Started by
19 comments, last by capn_midnight 16 years, 3 months ago
Quote:Original post by DvDmanDT
Search for XmlFormatter. I think it's pretty good, but missing something making it unusable for me. Perhaps it can be extended to handle it though?


Do you mean this one? I was playing with it, but it doesn't seem to do generic lists or dictionaries. There seem to be some bugs; the example there breaks if you remove the ISerializable implementation from their "MyObject" class, even though the object does nothing that the Binary or Soap formatters shouldn't be able to handle without implementing ISerializable. It seems like it could be a good starting point for developing something that could do what I want though.

The WCF method looks promising, but it's not supported under Mono at the moment, so it's not really useful to me. But I think they intend to support it at some point, so it may be a useful option in the future.
Advertisement
Quote:Original post by jpetrie
Quote:
True, you could write your own de/serialization functionality, but why not use what's in place already?

Well, there are occasionally valid reasons -- I manually(*) serialize my asset classes, for example, because the .NET serialization is quite verbose and not exactly easy to restore manually (e.g., from native C++ code).

(*) Rather, of course, my asset tool generates me code to serialize them manually.


Fair enough. Edge cases to tend to pop up from time to time, and they have to be dealt with, one way or another. As mentioned previously, I haven't too much experience with the XML Serializer yet, but it works pretty well for me, and I was too happy to switch from the manual technique.
Grant Palin
Quote:The problem is that all the resources I've found on Serialization never mentioned that methods can be tagged.


I bought a great book called "Pro C# 2005 and the .NET 2.0 Platform" some time ago and it's been a super easy and informative book. Explains all about the serialization and attributes. Also about the ISerializable interface as well. It's by Andrew Troelson. I'm sure they have a new version out by now.

Still, if you have VS2005 or later and have the help installed it should all be there. If you go to the VS2005 help (I think it's the msdn docs) and index one of the attributes and go to the about portion it should give info needed to use that attribute...

[the index from help]

OnDeserialized class
about OnDeserializedAttribute class
all members
...

[click on "about OnDeserializedAttribute class" to bring up super help...]

using System;using System.IO;using System.Runtime.Serialization;using System.Runtime.Serialization.Formatters.Binary;public class Test {    public static void Main()      {        // Create a new TestSimpleObject object.        TestSimpleObject obj = new TestSimpleObject();        Console.WriteLine("\n Before serialization the object contains: ");        obj.Print();        // Open a file and serialize the object into binary format.        Stream stream = File.Open("DataFile.dat", FileMode.Create);        BinaryFormatter formatter = new BinaryFormatter();        try        {            formatter.Serialize(stream, obj);                        // Print the object again to see the effect of the             //OnSerializedAttribute.            Console.WriteLine("\n After serialization the object contains: ");            obj.Print();            // Set the original variable to null.            obj = null;            stream.Close();              // Open the file "data.xml" and deserialize the object from it.            stream = File.Open("DataFile.dat", FileMode.Open);            // Deserialize the object from the data file.            obj = (TestSimpleObject)formatter.Deserialize(stream);            Console.WriteLine("\n After deserialization the object contains: ");            obj.Print();        }        catch (SerializationException se)        {            Console.WriteLine("Failed to serialize. Reason: " + se.Message);            throw;        }        catch (Exception exc)        {            Console.WriteLine("An exception occurred. Reason: " + exc.Message);            throw;        }        finally        {            stream.Close();            obj = null;            formatter = null;        }    }}// This is the object that will be serialized and deserialized.[Serializable()]		public class TestSimpleObject  {    // This member is serialized and deserialized with no change.    public int member1;    // The value of this field is set and reset during and     // after serialization.    private string member2;    // This field is not serialized. The OnDeserializedAttribute     // is used to set the member value after serialization.    [NonSerialized()]     public string member3;     // This field is set to null, but populated after deserialization.    private string member4;    // Constructor for the class.    public TestSimpleObject()     {        member1 = 11;        member2 = "Hello World!";        member3 = "This is a nonserialized value";        member4 = null;    }    public void Print()     {        Console.WriteLine("member1 = '{0}'", member1);        Console.WriteLine("member2 = '{0}'", member2);        Console.WriteLine("member3 = '{0}'", member3);        Console.WriteLine("member4 = '{0}'", member4);    }    [OnSerializing()]    internal void OnSerializingMethod(StreamingContext context)    {        member2 = "This value went into the data file during serialization.";    }    [OnSerialized()]    internal void OnSerializedMethod(StreamingContext context)    {        member2 = "This value was reset after serialization.";    }    [OnDeserializing()]    internal void OnDeserializingMethod(StreamingContext context)    {        member3 = "This value was set during deserialization";    }    [OnDeserialized()]    internal void OnDeserializedMethod(StreamingContext context)    {        member4 = "This value was set after deserialization.";    }    }// Output://  Before serialization the object contains: // member1 = '11'// member2 = 'Hello World!'// member3 = 'This is a nonserialized value'// member4 = ''////  After serialization the object contains: // member1 = '11'// member2 = 'This value was reset after serialization.'// member3 = 'This is a nonserialized value'// member4 = ''////  After deserialization the object contains: // member1 = '11'// member2 = 'This value went into the data file during serialization.'// member3 = 'This value was set during deserialization'// member4 = 'This value was set after deserialization.'


HTH,

Devin
Quote:Original post by DvDmanDT
The reason for this is that BinaryFormatter sometimes have problems with objects that change from serialization to deserialization. This happens quite often in my development process. Implenting ISerializable didn't help.


It is to be expected that binary serialization breaks if you modify the object being serialized/deserialized. Binary serialization can be thought of as taking the object and flattening it into a bytestream. There's no cataloguing or marking of individual pieces of data as with the XML serializer. If the object that we're attempting to load the serialized data into doesn't match exactly the runtime cannot deal with it -- type safety is extremely important in .NET. (Reminds me of the old EnvyMUD days when I'd use the first byte of a memory structure to determine what type of object it was... neat trick, but ultimately not safe.)

This lack of individual data separation is one of the reasons why the binary serializer beats the pants off the XML serializer in terms of data saved/memory used for serialization. The XML serializer uses "<RandomInt>4</RandomInt>" while the binary serializer uses "0004".

The XML formatter works in the opposite manner, which is why it only serializes public fields/properties. If a property doesn't exist, the XML formatter continues without complaining.

With ISerializable it IS noted that there is no guarantee as to the order of recreation. (I think this has more to do with the SerializationInfo object being parsed completely by the constructor before moving on to the next object in the graph than anything else.)

Can you not handle what you need to using the OnSerializing, OnSerialized, OnDeserializing, and OnDeserialized attributes? When one of the objects/properties/fields you're having problems with is either being prepared to be deserialized or has been, take whatever steps are necessary? Or is that your reference to breaking into parts/complexity?

With that said, custom serialization isn't bad. Especially if you're more concerned with storing data in a file rather than sending the object across remoting boundaries or app domains. I'm not a big fan of declarative programming (attribute based decision making) as it tends to hide itself and how it works.
..what we do will echo throughout eternity..
Sorry for the slightly off-topic question: if two classes have the same fields, but they're defined in different, non-accessible assemblies, would deserialization still be possible?

I am currently porting some code from VB.NET to C#, and I cannot reference the original assembly. I'd rather use serialization instead of reading bytes out of a file - which gets boring especially when dealing with arrays I guess.
Rainweaver Framework (working title)

IronLua (looking for a DLR expert)



Quote:Original post by Rainweaver
Sorry for the slightly off-topic question: if two classes have the same fields, but they're defined in different, non-accessible assemblies, would deserialization still be possible?

I am currently porting some code from VB.NET to C#, and I cannot reference the original assembly. I'd rather use serialization instead of reading bytes out of a file - which gets boring especially when dealing with arrays I guess.
I'm not sure about .NET serialization (I would guess that this is not possible), but WCF's DataContractSerializer was built to handle this scenario.

Thank you, mutex
Rainweaver Framework (working title)

IronLua (looking for a DLR expert)



Quote:Original post by Rainweaver
Sorry for the slightly off-topic question: if two classes have the same fields, but they're defined in different, non-accessible assemblies, would deserialization still be possible?

I am currently porting some code from VB.NET to C#, and I cannot reference the original assembly. I'd rather use serialization instead of reading bytes out of a file - which gets boring especially when dealing with arrays I guess.


XML serialization would handle this situation as well.
..what we do will echo throughout eternity..
I have just discovered serialization and I have to ask what's the point of it? Both binary and XML serialization end up with bigger files then if I just store my data in a text file and I dont see any speed advantage at all except maybe with loading but certainly not with saving.
Quote:Original post by gp_s
I have just discovered serialization and I have to ask what's the point of it? Both binary and XML serialization end up with bigger files then if I just store my data in a text file and I dont see any speed advantage at all except maybe with loading but certainly not with saving.
Serialization can be complex and error-prone to write. It's generally easier to do something like WriteObject(stream, stuffToSerialize) than to write a dozen methods to serialize your data.

With XML serialization you also have the benefit of a standard format.

This topic is closed to new replies.

Advertisement