7

I'm working on application in C#, where I need to serialize and deserialize some classes into/from XML. This operations will be implemented in Class Library. I chose XMLSerialization class to serialize/deserialize these classes to XML file. As you know, this implementation uses reflection, which has the condition that the serialized/deserialized class needs to have a parameterless constructor. However, the serialized class has one parameter that is mandatory, which is good candidate as parameter for constructor, to be sure that it is properly initialized. I've created a manager class for serialization with two methods, one to store to file and one to load from file. I thought of multiple solutions:

  1. For serialized class create two constructors, one parameterless and other one with mandatory parameter. This class can be easily serialized, but can be badly initialized, which can cause problems (maybe in other places, for example if class is used in any web service).
  2. As this implementation is in class library, it is possible to create class A (to serialize), which will be public and will have one constructor with mandatory parameter. Managers methods will take as parameter this class A or return class A after is loaded. But internally I would create class B, which will be 1:1 as class A, but with parameterless constructor for serialization or deserialization purposes. This class B will be internal, which means, that it is visible only in current assembly, so it cannot happen, that it can be badly initialized when class library is linked. However, this causes duplicate code. Imagine, that there can be more classes like this and more complex. This means another expense.
  3. Last one solution, which comes to my mind is to implement serialization by myself using Linq to XML. This solution is safe and without duplicate code, but implementation is difficult for big classes. Or even worse, when we want to change element names or switch between elements and attributes, we have to go through this implementation every time carefully and change it (instead of changing attributes).

As I'm trying to find out a better solution (maybe there is another, which I don't know about) and get good manners in programming applications. What do you think, what is better solution (maybe in one scenario and in other scenario another solution)? To maintan duplicate code or complex code (maybe from real experience)?

2
  • What is the purpose of the single-parameter constructor? May 13, 2016 at 20:58
  • For example: you want to store some data to file and you have entropy (byte array) used to encrypt this data. Or maybe service with som information needed for login or communication with it (security string, ...). Is that, what are you asking? May 13, 2016 at 21:17

4 Answers 4

3

I would just treat the classes you're going to serialize and deserialize as DTO's, and choose which utility method you wish to perform the serialization/deserialization. That way you only need a single class to carry the information.

Each utility method can contain some parameter validation, if you're worried about a bad parameter. If you want to keep the methods in the DTO, create a couple of factory methods that accept a serialization data source and return a DTO.

The one thing I would not do is have two model classes just because you want to automagically new up one, but manually new up the other with an enforced constructor. That creates two different places for your data, and violates the Single Source of Truth principle.

Keep it simple, soldier.

2

I find it quite annoying that many serialization libraries require parameterless constructors.

With the ability to annotate parameters, one could in theory specify associations between constructor parameters and serialization elements, so that the serialization library can collect all the necessary elements and pass them to the constructor of the deserialized object. Alas, I have yet to come across a serialization library that offers such a feature.

Furthermore, the ability to serialize objects with parametrized constructors is necessary even if we are not planning to parametrize them with deserialized values; for example, in order to implement Dependency Injection without resorting to magic like Spring.NET.

As far as I know, the way most people handle this is by having two separate sets of classes, one for the application logic to work with, and one for serialization only.

It turns out that this is not too bad, because the data model that you want to work with in your application logic is usually not the exact same as the data model that makes sense to persist.

For example, you may want to have the freedom to change your application data model while maintaining compatibility with serialization files that were created from older versions of your data model. If one set of classes is all you have, then the moment you make a change to your data model, all of your old data are suddenly unreadable. If you maintain your application data model separately from your serialization data model, then you can have different (concurrently existing) versions of your serialization data model for use with different versions of existing serialization files.

6
  • 3
    Maintaining two separate sets of classes just because serialization libraries require parameterless constructors is one of those situations where the cost exceeds the benefits. May 13, 2016 at 23:34
  • @RobertHarvey he makes a good point about backward compatibility with old files. I've run into that situation before myself. Of course, I don't think I would introduce a second set of classes until it was actually a problem to be solved though.
    – RubberDuck
    May 14, 2016 at 15:09
  • I find it quite understandable that many serialization libraries require parameterless constructors, because it helps to keep the serialization mechanics much simpler and cleaner-
    – Doc Brown
    May 14, 2016 at 15:12
  • @RobertHarvey I read your answer. I agree that it would be a bad idea to have a separate persistence data model just because of parameterless constructors. But I think my answer is making a much stronger point.
    – Mike Nakis
    May 14, 2016 at 19:48
  • @DocBrown I would think that the purpose of a library is primarily to make things simpler and cleaner for consumers of the library, not necessarily for the library itself.
    – Mike Nakis
    May 14, 2016 at 19:50
2

Keep this pragmatic - creating a lot of duplicate or boilerplate code should be a no-go, as well as reimplementing a mature serialization mechanism of the framework by yourself. So bite the bullet and provide a parameterless constructor - this, in reality, does not turn out to be so bad as you might think.

You can make the constructor private and provide a static method inside of the class for deserialization, which makes sure the "mandatory constructor attribute" is passed into the object after deserialization. That makes it at least unlikely someone will forget to set the additional attribute.

7
  • Is "byte the bullet" some pun I'm not getting or just a typo?
    – svick
    May 14, 2016 at 0:51
  • "Bite the bullet" is an idiom meaning to endure something painful or difficult: english.stackexchange.com/q/247999/151980. And "byte" in this referring to enduring something painful related to computers :) May 14, 2016 at 14:52
  • Hey guys, it was just a typo, and I corrected it already.
    – Doc Brown
    May 14, 2016 at 15:10
  • Doc, most of the serialization library's I've worked with require a public parameterless ctor.
    – RubberDuck
    May 14, 2016 at 15:10
  • I actually liked the unintentional pun...
    – RubberDuck
    May 14, 2016 at 15:11
1

What about two static methods in the class for seralize and de serailize. The parameter is a argument of this funuction and is stored as a constant somewhere.

If you end up having lots of these objects, make a class which has a list of these. This should have the ability to relate the methods on the whole list. It would also take a filter delegate and give a new list after filtering (don't delete data before saving). It would also the two static methods. The class and the one other parameter are arguments.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.