views:

72

answers:

1

Hi, I'm trying to send a message with an IEnumerable property, am i correct that the NServiceBus Xml serializer cannot support this ? If i switch to using an array rather than IEnumerable it will work, if i use the binary serializer it also works

My message look like this

[Serializable]
public class Parent : IMessage
{
  public string Identifier { get; private set; }
  public IEnumerable<Child> Children { get; private set; }

  public Parent(string identifier, IEnumerable<Child> children)
  {
    this.Identifier = identifier;
    this.Children = children;
  }
}

[Serializable]
public class Child
{
  public string Identifier { get; private set; }
}  

If the default Xml serializer cannot cater for this, is there any way to configure an alternative Xml serializer such as the BCL's DataContractSerializer ?

Thanks in advance

Pat

+1  A: 

First, a note that XML serialization in NServiceBus is not the same thing as .NET XML Serialization. The .NET variant is all about being able to tailor the resultant XML with attributes to produce specific XML schemas, potentially for interoperability with other languages. The NServiceBus XML serializer is an extremely small subset of functionality tailored to transfer predefined message schemas to and from XML as efficiently as possible.

While the result of NServiceBus serialization is readable (which is really nice when inspecting error queues) it doesn't support all types or all formatting options. It does what it does and it does it pretty well.

That said, the problem with an IEnumerable is that it could be so many things. It could, in reality, just be an array, but it could just as easily be a complex Linq-to-SQL expression that will invoke a database query. In order to serialize the IEnumerable, you'd have to represent it as a collection (a list or array) anyway, so you have to enumerate the items. When exactly would you do that? What problems with transactions might that raise? That's why the performance-conscious NServiceBus XML serializer doesn't bother.

An NServiceBus message is just a contract to pass message data. I would suggest just using an array. It's easy enough to convert an IEnumerable to an array (with the ToArray() extension method) and back (with the AsEnumerable() extension method) so why is it important to have it as an IEnumerable?

To fully answer your question, it should be possible to swap out the serializer by writing your own class that implements IMessageSerializer and configuring the dependency injection framework to use it, but I have not tried this myself. It would be quite an undertaking, since every single endpoint would have to utilize this same serializer, and you'd also have to make modifications in order to use the Distributor, TimeoutManager, Gateway, etc.

Edit: Noticed this question was cross-posted on NSB group at http://tech.groups.yahoo.com/group/nservicebus/message/8838

David
I've seent that the Xml serialization is taken care of in the NServiceBus.Serializers.XML.MessageSerializer type. The reason we wanted to go with IEnumerable was so that our messages would be immutable (Note the private sets in the properties). If i use an array the messages are no longer immutable as i can change an array item using the indexer and replacing the existing item with a new item. As you point out the delayed evaluation with IEnumerable is a problem. Thanks Pat
pmcgrath
@pmcgrath: I've battled with the whole mutable/immutable arguement but have come to the conclusion that it shouldn't matter if your messages are mutable as they shouldn't be your domain objects. The receiver should take the message and reconstruct that into a domain entity that is relevant for the task(s) it is about to preform.
Paul Hadfield