• We’re currently investigating an issue related to the forum theme and styling that is impacting page layout and visual formatting. The problem has been identified, and we are actively working on a resolution. There is no impact to user data or functionality, this is strictly a front-end display issue. We’ll post an update once the fix has been deployed. Thanks for your patience while we get this sorted.

I think I'm in love

xtknight

Elite Member
If you haven't checked out serialization, you should now. It will save you hours and sleepless nights.

The premise is that you can add a [Serializable] above class definitions and have the language save all members of the class to a file for you. You don't have to write a single line of code to convert your objects into binary form; .NET does it for you.

Essentially, I architected my program so that I had a "Project" class, and then serialized this class. After that, loading it in is really simple. You can cast a read from an input stream to the object itself and access it just as it was.

I realize this feature isn't "brand new" but I hope this will convince some of the skeptics or those more afraid of new features.

I found this article really helpful: http://msdn.microsoft.com/en-u...y/4abbf6k0(VS.71).aspx

You do have to be careful not to serialize file or object handles. They are not always the same. For these variables, and for events, you can prefix the line with [field: NonSerialized] and it will not be written to the file. If you don't do this, it might complain about something higher up like a form not being serialized.

I would like to know what you have against or for serialization. I found it really helpful for my project.
 
Coming from the other side of the aisle, how is this different from Java? You can push the object out through a wrapped stream, and read it back in the same way. Any non-serializable fields need to marked as transient (analogous to your [field:NonSerialized] compiler instruction).
 
Originally posted by: mundane
Coming from the other side of the aisle, how is this different from Java? You can push the object out through a wrapped stream, and read it back in the same way. Any non-serializable fields need to marked as transient (analogous to your [field:NonSerialized] compiler instruction).

It's probably not different but better than writing all the functions to write to a file yourself.
 
I seem to remember there being issues with certain things not being serializable. Collections, I think, choked on serialization, and that gave me trouble.
 
I :heart: serialization too, and have found it useful in quite a few projects. 🙂

Originally posted by: PhatoseAlpha
I seem to remember there being issues with certain things not being serializable. Collections, I think, choked on serialization, and that gave me trouble.

You can serialize a collection by first declaring the types of data stored in the collection due to .Net collections being weakly typed.
 
I haven't had a problem serializing collections, as long as the thing being pointed to is serializable. I usually don't do auto-serialization, though. I typically implement ISerializable, which isn't hard at all, and gives me some control over the process.

As for the Java comparison... C# is Java++, so I don't know what the argument is about 😉.
 
Maybe you have spoken too early. You haven't had to deal with versioning and serialized types. It is a nightmare (specifically, the SerializableAttribute) when you have to serialize/deserialize different versions of the same object or when you're inheriting from a type that is nonserializable. You'll run into the infamous "Cannot convert Type 'Cat' to Type 'Cat'" exception.

Refer to this article for details: http://www.vbinfozine.com/a_serialization.shtml

Again, this is not a bad thing, just that you need to be cognizant of the fact that merely marking your types with the [Serializable] attribute isn't always going to work. Implementing ISerializable can be tedious if you have a huge library, but once it's done, maintaining your APIs is a much better experience.

For .NET 3.5, specifically WCF, refer to Sowmy's blog for serializing BCL types: http://blogs.msdn.com/sowmy/ar...2006/02/22/536747.aspx
 
When I fist started coding in .Net back int he 1.1 days, I didnt know about serialization. could have saved my self about a month's worth of work creating file I/O routines for my data objects.
 
Originally posted by: Dhaval00
Maybe you have spoken too early. You haven't had to deal with versioning and serialized types. It is a nightmare (specifically, the SerializableAttribute) when you have to serialize/deserialize different versions of the same object or when you're inheriting from a type that is nonserializable. You'll run into the infamous "Cannot convert Type 'Cat' to Type 'Cat'" exception.

Refer to this article for details: http://www.vbinfozine.com/a_serialization.shtml

Again, this is not a bad thing, just that you need to be cognizant of the fact that merely marking your types with the [Serializable] attribute isn't always going to work. Implementing ISerializable can be tedious if you have a huge library, but once it's done, maintaining your APIs is a much better experience.

For .NET 3.5, specifically WCF, refer to Sowmy's blog for serializing BCL types: http://blogs.msdn.com/sowmy/ar...2006/02/22/536747.aspx

That's good to know. There may be some luck involved with my situation.

He seems to be talking about events. Well you can't serialize events I think because they point to functions in memory, which may change the next time you use the application. So you just have to set these as non-serializable.

And all you have to do to get around the versioning is to be sure you put in an int for version at the first release of your app and don't forget to update it if there's major changes. That's going to happen even if you don't do serialization. For instance, many games store a version number in demos, save games, etc and don't let you load a version that is incompatible or too old.

I'm not saying automatic serialization is always the way to go. I might implement my own to make the output a little more compact. But if you needed something quick and fast at least you know it's there. And I find solace in the fact that languages have come this far. Sometimes it's nice to see something happen before your eyes because it gives you motivation to go further once you know you're "sorta" there already. I may implement a manual serialization before I jump to too many conclusions about what I already have, but in my testing it is working flawlessly.

Edit: the version int field wouldn't work if it actually throws an exception. But you could probably catch and deal with the exception anyway when a newer version of the file is loaded?

Originally posted by: PhatoseAlpha
I seem to remember there being issues with certain things not being serializable. Collections, I think, choked on serialization, and that gave me trouble.

I tested this by serializing a Dictionary<int,string> and it worked fine. There may be some improvements in later versions. My original project had many collections of my own types of classes as well. I am just surprised it worked as well and fast as it did.
 
Surely, there are things that can't be serialized like events and delegates. I was just trying to make you aware of the fact that there are multiple issues that you could [or people behind you] could run into. I was the happiest individual the day I first serialized an object and stored in a DB. Three months later, customized my types, made modifications, and voila... serialization's broke.

Originally posted by: xtknight
Edit: the version int field wouldn't work if it actually throws an exception. But you could probably catch and deal with the exception anyway when a newer version of the file is loaded?

This is not a very good programming approach. It is like saying I'll catch the ThreadAbort exception and do my clean up work in the catch block without acknowledging the concepts of the ThreadAbort exception.

Refer to this blog entry with regards to the InvalidCastException I pointed earlier: http://www.hanselman.com/blog/...verToTypeWhatever.aspx

Suzzane Cook on the CLR team had an extensive blog entry a few years ago on this subject:
For example, path matters when determining whether a type is castable to another type. Even if the assemblies containing the types are identical, if they're loaded from different paths, they're considered different assemblies and therefore their types are different. This is one reason why using contexts other than the Load context is risky. You can get into situations where the same assembly is loaded multiple times in the same appdomain (once in the Load context, once in the LoadFrom context, and even several times in neither context), and their corresponding types won't be castable..

The reason why I keep nagging you is I have had to maintain other people's code who did not implement ISerializable, but simply adorned their types with [Serializable]. I can guarantee you that you'll run into hoards of issues when you deal with serialized objects and are trying to load objects dynamically (vis a vis Reflection).

Just be careful, and do it right the first time 😉.
 
Originally posted by: Dhaval00
Surely, there are things that can't be serialized like events and delegates. I was just trying to make you aware of the fact that there are multiple issues that you could [or people behind you] could run into. I was the happiest individual the day I first serialized an object and stored in a DB. Three months later, customized my types, made modifications, and voila... serialization's broke.

Originally posted by: xtknight
Edit: the version int field wouldn't work if it actually throws an exception. But you could probably catch and deal with the exception anyway when a newer version of the file is loaded?

This is not a very good programming approach. It is like saying I'll catch the ThreadAbort exception and do my clean up work in the catch block without acknowledging the concepts of the ThreadAbort exception.

My idea here was to tell the user he is using a version of my program too old to handle the file he is loading. I would probably just terminate the open file operation completely. Are you saying that catching the exception is a bad way to do that? It is possible there's another reason the exception could have been thrown and that I showed the user the message I didn't want to, but then it would be a toss-up what to do at that point anyway (basically an unhandled exception). The way I see it, I can be pretty sure an InvalidCastException is being thrown at that particular point because of one reason and one reason only. As long as .NET has the exception handling framework I may as well utilize it at little performance hit. (I don't even want to get into threading.)

[To me it's akin to using int.TryParse() when unsure and handling things from there. I don't see problems with using the try/catch process.]

Refer to this blog entry with regards to the InvalidCastException I pointed earlier: http://www.hanselman.com/blog/...verToTypeWhatever.aspx

Suzzane Cook on the CLR team had an extensive blog entry a few years ago on this subject:
For example, path matters when determining whether a type is castable to another type. Even if the assemblies containing the types are identical, if they're loaded from different paths, they're considered different assemblies and therefore their types are different. This is one reason why using contexts other than the Load context is risky. You can get into situations where the same assembly is loaded multiple times in the same appdomain (once in the Load context, once in the LoadFrom context, and even several times in neither context), and their corresponding types won't be castable..

The reason why I keep nagging you is I have had to maintain other people's code who did not implement ISerializable, but simply adorned their types with [Serializable]. I can guarantee you that you'll run into hoards of issues when you deal with serialized objects and are trying to load objects dynamically (vis a vis Reflection).

Just be careful, and do it right the first time 😉.

These look like things to keep in mind for the future, but may not apply to my rather simple program. What I do is I input several text files that belong together, process their contents into a bunch of classes to collect all the data, modify some of the data, then serialize all this out into a file that I can easily import again. At this point it's all in one file and not split into multiple txts anymore, has the modifications, and it's also easier to read in. I have the ability to export to standard formats: (at the least) MS Access Database and SQL.

Can you be more specific on what kinds of problems you ran into when you "maintained" the code? Do you mean that you were trying to load a class from that program into another program and had path problems, or you tried to add a feature to the old program and then realized your old files wouldn't import anymore (versioning)? DId you experiment with ways to work around it or did you decide at that point just to implement ISerializable manually?

I don't want it to be frustrating for others to maintain my code. Since my program has other export functions (output MS Access or SQL), I don't think anyone will have to "late bind" my objects into their programs. At worst they will have to add some features to my program, which as long as I implement the versioning framework should not be a difficulty. Am I wrong in assuming that?

I will take a look at implementing ISerializable myself. There is always that "black box" feeling when things work automatically. I am just wondering if automatically doing it all has innate inabilities or whether or not they can be worked around for Joe Sixpack who is not ready to implement ISerializable himself for the whole project when it could just introduce more problems.

In either case, I'm going to wait for your response before I release my program (that's a while away) because you have been very helpful in raising issues about the automatic method. Thanks. You're not raining on my parade, I just want to be sure of the limitations before I decide to undertake implementing it all manually. I need to decide if that's really worth it or not. I know by now I could have done it already to be sure, but I wouldn't have learned anything. 🙂
 
Originally posted by: xtknight
My idea here was to tell the user he is using a version of my program too old to handle the file he is loading. I would probably just terminate the open file operation completely. Are you saying that catching the exception is a bad way to do that? It is possible there's another reason the exception could have been thrown and that I showed the user the message I didn't want to, but then it would be a toss-up what to do at that point anyway (basically an unhandled exception). The way I see it, I can be pretty sure an InvalidCastException is being thrown at that particular point because of one reason and one reason only. As long as .NET has the exception handling framework I may as well utilize it at little performance hit. (I don't even want to get into threading.)

I was being hasty when I made that suggestion. For whatever reason, I was thinking of assemblies and FileLoadException. Nevertheless, be 100% sure that you have only one operation inside the try/catch block... I usually just wrap the single statement when I have to do recovery work. This way other operations can still "throw" their exceptions of the same type properly.

Can you be more specific on what kinds of problems you ran into when you "maintained" the code? Do you mean that you were trying to load a class from that program into another program and had path problems, or you tried to add a feature to the old program and then realized your old files wouldn't import anymore (versioning)? DId you experiment with ways to work around it or did you decide at that point just to implement ISerializable manually?

I don't want it to be frustrating for others to maintain my code. Since my program has other export functions (output MS Access or SQL), I don't think anyone will have to "late bind" my objects into their programs. At worst they will have to add some features to my program, which as long as I implement the versioning framework should not be a difficulty. Am I wrong in assuming that?

In my case the library had grown out of proportion and had multiple inheritance paths (all [Serialiable]). Since the automated .NET way wouldn't work, I had to go in and modify each and every base type to implement ISerializable. The situation was worsened by the fact that there were multiple base classes that were generic in nature... at one point in time, I was debugging the library for hours to try and find out just where the InvalidCastException was occurring. Believe it or not, the original programmer had the same mindset... "no one will ever inherit my types." LOL.
Once I was done fixing the base classes, I still kept running into InvalidCastException at the plugin level (Reflection). The reason was that the objects were being saved in different file paths and .NET remembers the file path when it serializes something automagically. This of course, screws up the probing process. Ultimately, turned out that I had forgotten to implement ISerializable on one of the base classes (thank god for the code reviews). Once that was in place, all the serialization/deserialization logic fell into place. Plus, I am the kind who has learned over time that it is always better to have finer control over certain things... via ISerializable, I can manage the code in anyway I want. In fact, I haven't had any issues with using these same types over WCF (but then I have data contracts in place, so I am unsure if .NET is using ISerializable or the DataContracts behind the scenes).
Of course, the obvious consequence of my actions was that I now am responsible for any serialization logic within my team, and it is not so much fun 😉.

I will take a look at implementing ISerializable myself. There is always that "black box" feeling when things work automatically. I am just wondering if automatically doing it all has innate inabilities or whether or not they can be worked around for Joe Sixpack who is not ready to implement ISerializable himself for the whole project when it could just introduce more problems.

Sure... there is nothing wrong with using what .NET and Java provide us at the highest level. But when there are people who have run into multiple issues previously with some of the features, it is best to heed their advice [which could be wrong]. I am no serialization guru, but my only motive is to prevent a fellow developer from making the same mistake that another developer made.

By the way, your class sounds simple. Implementing ISeriablizable should be a breeze.
 
This can work, as long as you do include a version int, and realize that you need to keep old class versions around if you ever change a class:

Say you have versions 10, 11, 12 as you've added fields to class foo. That means you need to have classes foo10, foo11, foo12 in your application, and fixups in foo12 to read and convert foo10 and foo11 files.

You also have to jump through hoops to write a version 10 or 11 document out in a version 12 program.

You're also at the mercy of Microsoft, if they ever change the serialization logic then newer compiles won't be able to read version 10 or 11 documents at all, even with version 10 or 11 classes.

These are reasons why geezers like me who've done years of maintenance programming would never touch black-box serialization with a 10 foot pole.

It's safer and more maintainable to create a document format and have functions to read and write the document format from fields in your classes, then:
- if you're reading a version 10 or 11 you fill in defaults for the missing fields that were addd for version 12
- if you still need to write version 10 or 11 docs you keep old versions of your write function, that don't know or care about any fields you added for version 12 (but you can still modify these legacy functions if needed)
 
Originally posted by: RocksteadyDotNet
You can't serialize generic classes = EPIC FAIL

Its a total PITA.

I would say your statement is not 100% accurate. If your type parameter is not serializable, the class itself may get corrupted during serialization. With regards to generics, one way I ensure my classes are serializable is by constraining the base class:

[Serializable]
public class SomeClass<W> where W : ISerializable
{
W obj;
}

You just need to know the proper techniques to force serialization to work... doesn't matter if you're dealing with generics or not. But as I mentioned earlier, it can be a total pain if you're dealing with complex hierarchies.
 
Back
Top