views:

38

answers:

3

Hi all,

With an application I'm currently developing I've come across the need to serialize some business objects to a number of different proprietary formats.

I'm struggling with coming to a decision on the best way to approach this and would like some opinions.

I know that .NET provides us with the ISerializable interface which I can implement on my business objects, however I'm struggling to understand how this would cope when I need to serialize to maybe 3 different formats?

On top of this I'm not too keen on the idea of having all of the serialization specific code "gumming up" my nice clean business objects - I'd prefer to parcel off that responsibility to a dedicated object. This seems to make sense as well when there are a number of different formats as serialization options could then be extended in the future by simply extending a base class, or modified without editing the business objects themselves. Then again, I'd rather not "re-invent the wheel".

I'm wondering what your collective experience and opinions are in cases like these?

Is ISerializable a viable option for multiple formats? Or is a custom class or service more suited to the task? Are there any design patterns or further framework features that cover this area?

+1  A: 

You can use ISerializable to get yourself a form of generic intermediate store of the data for each object (SerializationInfo), and you could then implement three separate handlers for that intermediate type to turn them into the final form. Personally I certainly wouldn't want to see three forms of serialization code in a single business object.

It may be simpler, depending on the number and complexity of your objects, for you to create your own interface which each class must support serializing to. This then allows you complete flexibility, at the cost of not being usable with the standard serialization bits.

Simon Steele
+1  A: 

Custom serialisation the .NET way, fully customised serialisation, just marking classes, and just marking classes and adding a few tweaks are all available:

Custom serialisation is useful when:

  1. An object is fully or partially immutable (one or more members is readonly) and hence must be deserialised via a constructor anyway (a factory method can also work by calling an existing constructor of course).
  2. A graph is complex, but much of it can be simplified with knowledge of the system (e.g. "I know I don't need to fully serialise that member I can just serialise enough information to create a new instance on deserialisation".
  3. A general-purpose class is used in a specific way (well, they always are...) and knowledge of those specifics can reduce the complexity of the graph.
  4. You are doing an XMLSeriazation of a class which inherits or implements a template class or abstract parameterised by itself (this goes into an infinite loop when mapping the graph, at least on IEnumerable<T>, I don't know if it happens for all such interfaces and I'm pretty sure it doesn't happen for binary serialisation - really it's a bug and should be fixed, but for the time being its there).
  5. You need to guarantee backwards and/or forwards compatibility with later versions of the class (up to you to make sure that works, but you've no hope if you aren't "in there").
  6. You have a member of a class that you can't edit (framework or third-part provided) that is not serialisable, so you need to provide your own method of serialising it.

ISerialisable will provide an abstraction (named things go in, named things come out) which is used in turn for different formats.

If you need a very specific format (e.g serialised in a particular pattern) then you may need to look at the other interfaces (e.g. IXmlSerializable) at being more explicit in use of the serialisation methods, or at ignoring .NET-provided serialisation techniques and rolling your own means to produce and parse the different formats.

At the other extreme, you can just put the [Serializable] attribute on the class and any class that it has a member of and that will give you default serialisation behaviour.

Further tweaks can come from putting [NonSerialized] on members that shouldn't be serialised (say you have BigObject _big; int _bigID and memoise access to _big by lazy-loading it based on _bigID on first access. In this case you can serialise just _bigID by marking _big as non-serialised. IDeserializationCallback allows further tweaks by informing your class when it has just been created by deserialisation.

Jon Hanna
A: 

Sounds like you need a custom serializer for each of the format you want to serialize your object to. As I mentioned in my comment, you can take the same object and serialize with the Json serializer and it'd give you a Json representation of that object, serialize it with XML serializer and you get XML, etc.

So for each of your formats you just need a custom serializer that can serialize/deserialize it to and from that format.

theburningmonk