2011-09-16 12 views
7

Tengo dos clases como abajo:WCF - Crear instancias de un objeto en DataContract constructor

[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 
} 

¿Qué sucederá si el genero de proxy de mi servicio que utiliza la clase de atención al cliente? Si entiendo el concepto correctamente, entonces creo que el constructor en la clase Cliente no será llamado por el lado del cliente y puede tener un comportamiento diferente.

¿Cómo me deshago de ese constructor en la clase Cliente y aún tengo la propiedad CustomerAddress del tipo Address para que se comporte como un objeto DTO estúpido?

¿Cuál es la pauta general o las mejores prácticas que las personas usan para evitar esta situación?

Respuesta

6

Si utiliza el valor predeterminado DataContractSerializer para serializar sus objetos, entonces, sí, su constructor no está serializado, y el cliente no invocará ninguna lógica que pueda tener cuando se deserialice el objeto.

En cuanto a su pregunta sobre la eliminación de la lógica del constructor y el hecho de que la clase anidada Address se rellene, eso será resuelto por DataContractSerializer. Si tengo un código como éste:

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

y luego regresar que a partir de un método de servicio, que Customer objeto será serializado adecuadamente junto con la información Address. El proxy en el cliente que se genera conocerá Address y podrá deserializar el flujo proveniente del método de servicio para construir correctamente su objeto Customer. Su Customer será un DTO ficticio, sin lógica, solo propiedades.

Eche un vistazo a Aaron Skonnard's MSDN article en WCF Serialization donde habla sobre el DataContractSerializer.

0

Será mejor que defina todas las clases de contrato de datos en un ensamblado y haga que tanto el proyecto del servidor como el proyecto del cliente hagan referencia al ensamblaje para poder compartir el comportamiento de inicialización. Al generar una referencia de servicio, puede indicar al generador de código que use clases de contrato de datos existentes.

1

Si generar el cliente (utilizando svcutil o "Agregar referencia de servicio"), entonces el DataContract generada se verá así:

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

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

Sus detalles de implementación no se transfieren. Todo lo que se genera es lo que entra en el WSDL, que es solo las propiedades [DataMember] en este caso.

Menciono esto porque su pregunta original pregunta: "¿Qué pasará si genero proxy".


Si se trata de un objeto que está siendo enviado desde el servidor al cliente, a continuación, puedes siempre inicializar CustomerAddress antes de enviarlo al cliente. De hecho, si su código original está en el servidor, entonces se ejecutará ese constructor, y WCF serializará el CustomerAddress y, básicamente, nunca enviará un nulo (a menos que lo vuelva a establecer como nulo después del constructor).

Si quieres hacerlo de modo que el cliente siempre le envía un CustomerAddress, a continuación, usted podría:

  • tienen la servidor cheque por nula, como if(x.CustomerAddress == null) x.CustomerAddress = new Address();
  • marcar el DataMember según sea necesario, entonces el servidor devolverá un error si el cliente no pasó nada: [DataMember(IsRequired=true)] public Address CustomerAddress;

De lo contrario, no creo que haya ninguna manera de forzar la generación d Cliente WCF para inicializar ese campo por usted.

Cuestiones relacionadas