2011-09-16 1 views
7

Ho due classi come qui sotto:WCF - di un'istanza di un oggetto in DataContract costruttore

[DataContract] 
public class Address 
{ 
    [DataMember] 
    public string Line1 
    [DataMember] 
    public string Line2 
    [DataMember] 
    public string City 
    [DataMember] 
    public string State 
    [DataMember] 
    public string Zip 
} 

[DataContract] 
public class Customer 
{ 
    public Customer() 
    { 
     CustomerAddress = new Address(); 
    } 

    [DataMember] 
    public string FirstName 
    [DataMember] 
    public string LastName 
    [DataMember] 
    public Address CustomerAddress 
} 

Cosa accadrà se genero delega del mio servizio che utilizza la classe Cliente? Se capisco correttamente il concetto, penso che il costruttore nella classe Customer non sarà chiamato dal lato client e potrebbe dare un comportamento diverso.

Come faccio a sbarazzarmi di quel costruttore nella classe Cliente e ho ancora la proprietà CustomerAddress di tipo Address in modo che si comporti come un oggetto DTO stupido?

Qual è la linea guida o le migliori prassi generali che le persone utilizzano per evitare questa situazione?

risposta

6

Se si utilizza l'impostazione predefinita DataContractSerializer per serializzare i propri oggetti, quindi, sì, il costruttore non è serializzato e qualsiasi logica eventualmente contenuta in esso non verrà chiamata dal client quando l'oggetto viene deserializzato.

Per quanto riguarda la domanda relativa alla rimozione della logica del costruttore e l'inserimento della classe nidificata Address, questa sarà gestita dallo DataContractSerializer. Se ho il codice come questo:

Customer c = new Customer() { 
    FirstName = "David", 
    LastName = "Hoerster", 
    CustomerAddress = new Address() { 
    Line1 = "1 Main Street", 
    City = "Smallville", 
    State = "AA", 
    Zip = "12345" 
    } 
}; 

e poi tornare che da un metodo di servizio, che Customer oggetto verrà serializzato correttamente insieme alle informazioni Address. Il proxy sul client che verrà generato saprà di Address e sarà in grado di deserializzare lo stream proveniente dal metodo di servizio per costruire correttamente l'oggetto Customer. Il tuo Customer sarà un DTO fittizio - nessuna logica, solo proprietà.

Controllare il numero MSDN article di Aaron Skonnard sulla serializzazione WCF in cui parla di DataContractSerializer.

0

È consigliabile definire tutte le classi di contratto dati in un assieme e fare riferimento sia al progetto server che al progetto client all'assieme in modo che il comportamento di inizializzazione possa essere condiviso. Quando si genera il riferimento al servizio, è possibile indicare al generatore di codice di utilizzare le classi di contratto dati esistenti.

1

Se generare client (utilizzando svcutil o "Aggiungi riferimento al servizio"), allora la DataContract generato sarà simile:

[DataContract] 
public class Customer 
{ 
    // empty default constructor 
    public Customer() 
    { 
    } 

    [DataMember] 
    public string FirstName 
    [DataMember] 
    public string LastName 
    [DataMember] 
    public Address CustomerAddress 
} 

I suoi dettagli di implementazione non sono riportati. Tutto ciò che viene generato è ciò che entra nel WSDL, che è solo le proprietà [DataMember] in questo caso.

Dico questo perché la tua domanda originale chiede: "Cosa succederà se genero il proxy".


Se si tratta di un oggetto che viene inviato dal server al client, allora si può solo sempre inizializzare CustomerAddress prima di inviarlo al client. Infatti, se il codice originale è sul server, verrà eseguito quel costruttore e WCF serializzerà lo CustomerAddress e in pratica non invierà mai un valore null (a meno che non lo si imposti su null dopo il costruttore).

Se si vuole fare in modo che il cliente si invia sempre un CustomerAddress, allora si potrebbe:

  • hanno la controllo server per nulla, come if(x.CustomerAddress == null) x.CustomerAddress = new Address();
  • segnare il DataMember come richiesto, quindi il server restituirà un errore se il client non ha passato nulla: [DataMember(IsRequired=true)] public Address CustomerAddress;

Altrimenti, non penso ci sia alcun modo per forzare il generare d client WCF per inizializzare quel campo per te.