tags:

views:

51

answers:

2

NServiceBus creates concrete implementation classes from interfaces to uses as messages. This is in theory to allow for the composition of these messages from other messages. In effect allowing for multiple inheritance. To demonstrate the inconsistent behavior I created a few test interfaces:

public interface ITestBase1
{
    string Property1 { get; set; }
}

public interface ITestBase2 : ITestBase1
{

}

public interface ITestBase3 : ITestBase2
{

}

I then ran the following code:

var types = new[] { typeof(ITestBase1) };

new NServiceBus.MessageInterfaces.MessageMapper.Reflection.MessageMapper().Initialize(types);

var msg = new NServiceBus.MessageInterfaces.MessageMapper.Reflection.MessageMapper().CreateInstance(typeof(ITestBase1));

If I create concrete implementation of ITestBase1 I find exactly what I would expect. One Property called Property1. If I create concrete implementation of ITestBase2, I find msg has one Property1 property.

If I create concrete implementation of ITestBase3, however, I get two implementation of Property1 on the msg object. One for the ITestBase1 and one for the ITestBase2 interfaces. This seems a bit counter intuitive to me. I would expect the number of Property1 implementations on the base message to not vary. This makes it quite confusing when trying to build messages out of components.

Short of modifying the messagemapper.GetAllProperties code of nservicebus is there a way around this behavior? I would rather not have the other interfaces create new properties of the same datatype and name.

A: 

My understanding of the purpose of the concrete implementations is:

  1. so that no implementation is required in the subscribing service, and
  2. to enable convenience creation of simple messages, eg:

    Bus.Publish<IMyMessage>(m => { m.Property1 = "My Value"; });

I'm struggling to envisage a scenario where you'd need to create your own instances directly. Can you elaborate on what you're doing here?

Sam
http://www.nservicebus.com/MessagesAsInterfaces.aspx
ModPsiSquared
"The other reason to use interfaces is that they enable multiple inheritance, which is very useful for extending a system over time from one version to the next, without breaking existing subscribers. "
ModPsiSquared
In this case I'm merely describing that the concrete class that is created by nservicebus reqquires that you cast it carefully. If Interface A derives from B derives from C. C is created in the B and C classes as seperately backed properties. Set (item as B).Property1 = 1 and you have not set (item as C).Property1. The latter is still undefined. The concrete class created for you by nservicebus can seriously obfuscate where heirarchies are deeper than two level. This is counter to the above quote from the documentation.
ModPsiSquared
If you're publishing a versioned message, I would expect you'd want to create your own implementation. Non-trivial version changes will probably require custom code to support previous version at any rate. Subscribers to a versioned message should only ever interact with the specific version they have subscribed to. I'm still not sure why you would need to cast the message?
Sam