2010-09-29 18 views
7

Estoy tratando de crear una clase con un campo Id de solo lectura, sin embargo, tengo problemas para retener el valor cuando el objeto pasa a través del servidor WCF.Atributo WCF DataMember para campos de solo lectura?

No puedo establecer el atributo [DataMember] en la propiedad pública ya que no existe el método set, y me gustaría mantenerlo así si es posible ya que no quiero que este valor cambie por medios externos. No puedo establecer el atributo [DataMember] en el campo privado, ya que arroja un error en los entornos de confianza parcial.

public class MyClass 
{ 
    private int _id; 

    public int Id 
    { 
     get { return _id; } 
    } 

    private string _otherProperties; 

    [DataMember] 
    public string OtherProperties 
    { 
     get { return _otherProperties; } 
     set { _otherProperties = value; } 
    } 
} 

¿Hay alguna manera de mantener el valor del campo Id mientras se pasa por el servidor WCF sin hacer que mi propiedad sea pública?

+0

http://msdn.microsoft.com/en-us/library/ms733127.aspx: No debería arrojar un error si tiene un método privado. Puede ver en la nota: que a DataContract no le importa la visibilidad del método. –

Respuesta

7

En general, sus clases de contrato de datos deben ser objetos de transferencia de datos muy livianos sin ninguna lógica o un significado más profundo asociado a ellos. Solo contenedores para transportar datos a través de la nube. Deben ser clases públicas, con solo un conjunto de propiedades públicas de lectura y escritura. En las clases de lógica empresarial, debe convertirlas en algunas entidades comerciales internas y hacer lo contrario al transmitir datos.

Esto separa el modelo de transferencia de datos de cualquier modelo de entidad interna y garantiza un mantenimiento óptimo, lo que le permite evitar problemas como el que enfrenta, donde los problemas de diseño de OO entran en conflicto con el comportamiento operativo de WCF.

Con proyectos muy pequeños, la sobrecarga de mantener un modelo separado podría no valer la pena. AutoMapper puede ser de alguna ayuda para minimizar el trabajo manual requerido.

Hablando de su situación específica, no estoy seguro de entender exactamente la declaración del problema. ¿No quieres que se modifique algún campo? Pero este campo es solo una parte del modelo de datos: las partes del modelo de datos nunca se "modifican", no hay datos "antiguos", solo datos que su cliente inventa. Su código de cliente simplemente envía un objeto de datos al servidor. Si el servidor no se preocupa por un miembro de la clase, simplemente debe ignorarlo.

No es que existan instnaciones de los objetos del contrato de datos en el servidor y esperen a que los clientes los manipulen. Un campo de solo lectura podría tener sentido conceptualmente en tal escenario, pero esto no es así con WCF. El cliente simplemente crea un objeto y lo envía al servidor. Si no desea que el servidor escuche algunos datos, no los agregue al modelo de datos o (si tal vez a veces es necesario, solo para usuarios específicos o similares) haga que el servidor los ignore cuando no lo desee.

+0

Déjame ver si tengo esto claro ...sugieres que cada objeto debe tener dos partes: una clase DataTransfer (DataContract) para enviar/recibir datos hacia/desde el servidor WCF y la propia clase en sí que contiene la lógica de negocios, INotifyPropertyChanged, funcionalidad, etc. – Rachel

+0

Sí y no. Los objetos de transferencia de datos no necesitan en realidad correlacionar uno a uno con ningún objeto de lógica de negocios. Por ejemplo, podría tener un objeto comercial de Empleado grande y complejo, pero sobre mis diversas operaciones de WCF, expongo los datos relevantes para la operación en particular. P.ej. UpdateContactInfo (ID de empleado de Guid, información de ContactInfo) solo llevaría la información de contacto, mientras que aún podría formar parte de mi objeto comercial Employee. Sin embargo, para pequeños escenarios, el objeto de transferencia de datos y el objeto comercial tienden a ser casi idénticos, simplemente sin ningún campo "indeseable" (por ejemplo, hash de contraseña). – Sander

1

No. El miembro de datos tiene que tener getter y setter para ser serializable. Es responsabilidad del servicio validar que Id no se modificó en el cliente.

7

Usted puede hacer esto:

public int Id 
{ 
    get; 
    private set; 
} 

Esto evitará que el deserializer feliz, si bien no dejar que la gente en realidad establecer el valor de ID. Tendrás que configurarlo en el constructor o en el setter de otra propiedad.

Sin embargo, estoy de acuerdo con Sanders, en que su DTO debe ser un contenedor tonto.

Cuestiones relacionadas