views:

378

answers:

2

So I have two separate applications that I want to send messages between. I happen to be using NServiceBus, but that shouldn't really matter. How do I send a message from application A to application B and have them both be aware of the same contract?

So app A has a class SecretMessage...

public class SecretMessage : IMessage
{
     public string Title { get; set; }
     public string Body { get; set; }
}

This is the object that will be serialized and sent over the wire to app B.

Now in app B, how do I listen for messages that are of that type and then be able to de-serialze them to the same class? So I can use the data as it was sent, without this being a maintenance nightmare.

Does app B just have to have a copy of the class? Should this be handled through a shared dll of message classes that each app has a reference to (I hope not)? Should they be recreated in each app as completely separate DTO's with the same properties?

Am I missing something here?

+5  A: 

It may not be the answer you want but there are very few silver bullets here.

You've really only got a few choices, and as such then depends on the level of functionality and type-hardening you want in your message classes:

  1. Shared DLL's - benefit that it can be code + structure e.g. useful constructors, complex enumerators, debugging ToString implementations etc. Strong versioning. Requires separate project and distribution for DLL.
  2. Shared Schema and Code Generation. Declare schema for your types and use code generation to create classes. Lots of different strategies here - some examples: T4 Templating, Custom Code Generation, Tools and libraries such as CodeSmith or Proto.Bufs. Search will find you loads more. Can be pretty powerful - know many codeshops that start all projects through rapid prototyping with CodeGen from DB through to UI. You'd still need to distribute schema.
  3. Serializing message with enough fidelity to generate types through Code DOM. Each message incurs the cost of carrying enough type metadata to be representative of all it's message instances. e.g. representations of nullable fields. There would also be an intrinsic 1st time "discovery" cost to generate the message wrapper types.
  4. Serialize data in a weak structure such as name/value pairs, then generate dictionary-like wrapper classes. Weak typing - easy to extend tho'.

Those really are the only choices. IMHO #2 then #1 in that order are typically the most useful patterns.

stephbu
Brad Mellen-Crandell
Right - typically code generation happens either outside of the project and the results are imported, or within the project as a build item.
stephbu
+1  A: 

As suggested by Juval Lowy in Programming .NET Components, separate pure interfaces in their own shared DLL.

http://arcanecode.com/2007/02/14/more-oop-interfaces-in-c-part-2/

kenny