2009-08-26 19 views
7

Domanda nel titolo ... In breve - Ho un servizio WCF che espone le operazioni che restituiscono le classi di entità. Le classi lato client ereditano da una classe base astratta invece del System.Object predefinito. La classe base astratta ha definito un costruttore predefinito. Quando si chiama uno dei metodi di servizio, mi aspetto che venga richiamato il costruttore quando il serializzatore datacontract materializza gli oggetti restituiti. Tuttavia, il costruttore non viene chiamato. Se invece creo un'istanza della classe entità, viene chiamato il costruttore della classe astratta.Perché il costruttore della mia classe base astratta non viene chiamato quando un oggetto è inizializzato dal deserializzatore WCF?

Perché, oh perché, e c'è una soluzione? O mi sono perso qualcosa - c'è un'altra firma del costruttore che viene chiamata dal serializzatore datacontract quando materializza gli oggetti? In caso contrario, in che modo il serializzatore datacontract materializza gli oggetti senza chiamare i costruttori nello stesso modo in cui farebbe una chiamata "new SomeClass()"? Oppure bevevo troppo caffè oggi (avevo solo 2 o 3 tazze fino ad ora)?

risposta

11

WCF (e DataContractSerializer in particolare) non utilizza i costruttori. No, davvero (usa FormatterServices.GetUninitializedObject per creare oggetti grezzi).

Si prevede che tutti i dati verranno inizializzati dal serializzatore o per i campi non serializzati, mediante le richiamate di serializzazione aggiunte (ad esempio, tramite [OnDeserialized]).

+1

Grazie per la risposta rapida. Wow. Questo mi sorprende. Ho pensato che l'inizializzazione di tutti gli oggetti avrebbe comportato la chiamata di costruttori. Oh bene, ho imparato qualcosa di nuovo oggi ... :) – KristoferA

+0

È davvero piuttosto sorprendente. Ho dovuto scavare nel riflettore la prima volta che l'ho visto! –

+0

Una domanda di follow-up [per curiosità] sarebbe: _ perché ... l'hanno fatto in quel modo? Prestazione? Pasticciare con le nostre teste? O qualche altra ragione migliore? :) – KristoferA

1

Capisco perfettamente i motivi, ma non capisco perché non supportano i callback di serializzazione in Silverlight. Mi sembra che in una comunicazione WCF - Silverlight non possa inizializzare il mio contratto di dati senza hackerarmi. Quindi, se avessi un membro privato nella mia classe di base per uso interno (es. Scuci-cuci comportamento), non può utilizzare il costruttore di default:

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

Questo semplicemente non funziona. Per farlo funzionare dovrei scrivere qualcosa del genere:

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

Mi sembra una soluzione. Qualcuno ha idee migliori?

+0

Sembra una soluzione alternativa, ma devi assicurarti che non ci siano condizioni di competizione tra il controllo nullo e il setter, altrimenti puoi restituire una pila obsoleta per un thread. L'unico modo per risolverlo è utilizzare almeno OnDeserializing, creare un oggetto syncRoot = new object() e bloccarlo nel getter UndoStack (o creare direttamente l'istanza UndoStack in questo metodo. – eFloh

Problemi correlati