views:

53

answers:

2

Let's say I have an application that processes messages. Messages are just objects in this case that implements IMessage interface which is just a marker.

In this app, if a message fails to process, then I want to log it, first of all for auditing and troubleshooting purposes. Secondly I might want to use it for re-processing.

Ideally, I want the message to be serialized into a format that is human-readable. The first candidate is XML although there are others like JSON. If I were to serialize the messages as XML, I want to know whether the message object is XML-serializable. One way is to reflect on the type and to see if it has a parameter-less constructor and the other is to require IXmlSerializable interface. I'm not too happy with either of these approaches. There is a third option which is to try to serialize it and catch exceptions. This doesn't really help - I want to, in some way, stipulate that IMessage (or a derived type) should be xml-serializable.

The reflection route has obvious disadvantages such as security, performance, etc. IXmlSerializable route locks down my messages to one format, when in the future, I might want to change the serialization format to be JSON. The other thing is even the simplest objects now must implement ReadXml and WriteXml methods.

Is there a route that involves the least amount of work that lets me serialize an arbitrary object (as long as it implements the marker interface) into XML but not lock future messages into XML?

A: 

You could implement a MessageBase that all your message objects derive from that contains a parameterless constructor. Then use MessageBase rather than IMessage.

Curious though, if you design the messages and have the intention for them to all be serializable why do you need to check?

Here's a generic object extension I use a lot:

/// <summary>        
/// Converts an object to a serialized xml string       
/// </summary>
/// <param name="o">The <see cref="object"/> to serialize</param>
/// <returns></returns>
public static string ToXml(this object o)
{
    XmlSerializer xmlSerializer = new XmlSerializer(o.GetType());

    using (MemoryStream memoryStream = new MemoryStream())
    {
        using (StreamWriter streamWriter = new StreamWriter(memoryStream))
        {
            xmlSerializer.Serialize(streamWriter, o);
            streamWriter.Flush();
            memoryStream.Flush();
            memoryStream.Position = 0;

            using (StreamReader streamReader = new StreamReader(memoryStream))
            {
                return streamReader.ReadToEnd();
            }
        }
    }
}

Implement it on your MessageBase and you're golden. No locking in to anything.

Cory Charlton
Now the code must test against MessageBase to serialize, which kind of defeats the purpose of having IMessage in the first place.
Jiho Han
By the way, I use StringWriter/StringBuilder for xml serialization. Not sure what, if there is any, the differences are.
Jiho Han
Well yes. Personally an interface with no methods defeats the purpose for me. It doesn't indicate that you can actually *DO* anything specific with the object which is what you are trying to do. Represent that an object both contains the necessary methods for serialization and has been designed with proper objects that also can be serialized.
Cory Charlton
A: 

So the requirement is to serialize an arbitrary object (as long as it implements the marker interface) into human readable format (possibly XML) in the easiest possible manner.

As mentioned in Is It Serializable? determining if an object is serializable is hard.

I can think of only 2 ways to meet the requirements:

  1. Add a Serialize method to the IMessage interface and force classes to implement a their own human readable format.
  2. Have your application interface be exposed as a service that accepts a human readable format. e.g. a WCF service that accepts a human readable message (XML) that you can log.

Option 1 may be good for auditing but not so much for reprocessing. Also there are still some edge cases that might cause problems.

If this is an existing application then those are probably not viable options. If that is the case then maybe look at something like Json.NET to try to serialize on a best effort basis.

Tuzo