7
votes

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)?

2

2 Answers

13
votes

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]).

1
votes

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?