views:

339

answers:

2

Question in title... In short - I have a WCF service exposing operations that return entity classes. The client-side classes inherit from an abstract base class instead of the default System.Object. The abstract base class has a default constructor defined. When calling one of the service methods I would expect that constructor to get called when the datacontract serializer materialize the returned objects. However, the constructor is not called. If on the other hand I create an instance of the entity class myself then the abstract class constructor is called.

Why, oh why, and is there a workaround? Or did I miss something - is there another constructor signature that is called by the datacontract serializer when materializing objects? If not, how can the datacontract serializer materialize objects without calling the constructors the same way that a "new SomeClass()" call would do? Or did I drink too much coffee today (only had 2 or 3 cups so far)?

+7  A: 

WCF (and DataContractSerializer in particular) doesn't use constructors. No, really (it uses FormatterServices.GetUninitializedObject to create raw objects).

It is expected that all data will be initialized either by the serializer, or for non-serialized fields - by serialization callbacks that you add (for example, via [OnDeserialized]).

Marc Gravell
Thanks for the quick answer. Wow. That surprises me. I thought that all object initialization would result in constructors being called. Oh well, I learnt something new today... :)
KristoferA - Huagati.com
It is indeed rather surprising. I had to dig around in reflector the first time I saw it!
Marc Gravell
A follow up question [out of curiosity] would be: _why_ did they do it that way? Performance? To mess with our heads? Or some other better reason? :)
KristoferA - Huagati.com
The constructor may do something inappropriate. They goal, with any sort of deserialisation, is not to 'create a new object', but 'get the old object back'. To do this, you may actively need to avoid the constructor.
Noon Silk
Ok, so it is an attempt to protect us from ourselves then. :) It totally killed my productivity for the rest of the day. I'll finish this cup of coffee and then I'll go and have a beer instead... :)
KristoferA - Huagati.com
Hmm. This is actually better. I can now have both constructor and a method tagged with OnDeserialized in the abstract base class. Not bad at all. :)
KristoferA - Huagati.com
+1  A: 

I fully understand the reasons, however I do not understand why they do not support serialization callbacks in Silverlight. It seems to me, that in a WCF - Silverlight communication I cannot initialize my data contract without hacking myself. So, if I had a private member in my base class for internal use (eg. undo-redo behavior), cannot use the default constructor:

Stack<PropertyChange> UndoStack = new Stack<PropertyChange>();

This simply does not work. To make it work I should write something like this:

Stack<PropertyChange> _UndoStack;
Stack<PropertyChange> UndoStack
{
     get
     {
           return _UndoStack == null ? (_UndoStack = new Stack<PropertyChange>()) : _UndoStack;
     }
}

It seems a workaround to me. Anyone has better ideas?

danleis