Thursday, May 08, 2008

WCF and Inheritance

Anybody who has had the pleasure of working with WFC, or in fact any messaging based programing will understand the issues related to messaging and inheritance. For those that don't, here is a quick rundown.

Take this situation:
I have a person class with:
  • First Name
  • Last Name
  • Age

When serialised, I get something like this:

FirstName: Eddie
LastName: de Bear
Age: 30

Now this so far does not cause any problems. It's designed to work like this. When a service receives this message, it knows exactly what it is dealing with.. A Person.. That's what the contract defines, that's what it gets and deals with.


Now, Imagine I now have a new class Employee which inherits from Person and adds a single attribute, EmployeeId.

Now, when this gets serialised, what do we see:

FirstName: Eddie
LastName: de Bear
Age: 30
EmployeeId: XXX-123-XXX


(This assumes that the new Employee class still has the same contract name etc..)
Now, if this was passed to a Service that expects a person, the service has a little heart attack. It has no idea what to do with the new attribute EmployeeId.. It's not part of the person class..

There are a number of solutions to this, such as Method Overloading. But one of the solutions I find the most interesting is the mechanism WCF uses for Contract Versioning. IExtensibleObject.

In the example above, you could easily implement IExtensibleObject on the original person class. IExtensibleObject basically provides a property bag for dumping extra information that is encountered at deserialisation time. This allows the service to continue to treat the Employee object as a person, without loosing the additional information added by the employee class.

A great article on the use of the IExtensibleObject interface can be found Here

2 comments:

Rory said...

My preferred option is this:

[DataContract]
public class Person : PersonUpdateRequest

[DataContract]
[KnownType(typeof(Person))]
public class PersonUpdateRequest

Eddie de Bear said...

Rory,

Yes, this does work really well. What I believe the advantage of the IExtensibleObject is, is the fact that the property Extensions actually holds the additional information on the service side (the bits it couldn't de-serialise). This allows you to still access the "extra" information without changing your contract.

I believe this mechanism was actuall intended for versioning, not for nasty inheritance hacks.. And to be honest, I find I tend to design any inheritance out of my contracts to avoid the whole situation.. ;)