2009-02-17 34 views
53

En WCF, ¿cuál es la diferencia entre aplicar el atributo DataMember en una propiedadWCF: DataMember atributo en la propiedad vs. miembro de

private int m_SomeValue; 

[DataMember] 
public int SomeValue { 
    get {...} 
    set {...} 
} 

en lugar de una variable miembro

[DataMember] 
private int m_SomeValue; 

public int SomeValue { 
    get {...} 
    set {...} 
} 

?

+1

no necesita convertir una variable privada en un miembro de datos. –

Respuesta

41

En general, debe favorecer la aplicación del atributo DataMember en la propiedad, en lugar de en el campo privado. La única razón para aplicar el atributo al campo es si la propiedad era de solo lectura (es decir, no tiene setter).

+2

¿Por qué tenemos que hacer eso? – Krishna

+2

Toda la serialización en WCF es bidireccional por defecto. Esto significa que el marco debe poder leer y escribir todos sus elementos de datos.Por lo tanto, si está modificando un tipo existente con propiedades de solo lectura para ser serializable, es posible que deba agregar los atributos a un campo. Este es un caso raro, sin embargo. – dthrasher

+5

También es útil poner DataMemberAttribute en un campo si el getter/setter de su propiedad tiene algún código que pueda alterar su valor. – rossisdead

3

En teoría, y siempre que mantenga m_SomeValue siempre igual a SomeValue (como un simple getter/setter), nada. Aparte del nombre de la variable expuesta por el WCF. (Obviamente, si etiqueta la variable m_, su clase proxy también tendrá el mismo nombre m_. La clase proxy generará una propiedad pública si usa un campo o propiedad pública/protegida/interna/privada.

Sin embargo , si tiene alguna lógica especial en sus accesadores que pueda modificar el valor devuelto (ToUpper() ing string, por ejemplo), devolvería un valor diferente.

24

Siempre que use el marcador Name, el contrato es idéntico independientemente de si se utiliza el campo o la propiedad.

[DataMember(Name="SomeValue")] 
private int m_SomeValue; 

Sin embargo, puede haber algunos problemas de permisos para acceder a miembros privados, en particular en silverlight y CF, en cuyo caso recomendaría usar la propiedad pública como el miembro de datos. En realidad, tendería a siempre use una propiedad a menos que tuviera una muy buena razón ...

+0

Totalmente en desacuerdo con usted Marc, vea mi pregunta, me gustaría escuchar su respuesta en ella http://stackoverflow.com/a/8442768/235715 –

+0

@Alex respondió como se lo solicitó –

2

Personalmente, solo utilizaría la propiedad y eliminaría por completo la variable miembro todos juntos. es decir,

[DataMember] 
public int SomeValue 
{ get; set; } 

La propiedad creará inexplicablemente una variable miembro detrás de las escenas.

+7

"inexplicablemente"? Eso es lo que debe hacer. ¿Quizás quisiste decir "implícitamente"? –

+3

¿Cómo lo sabes? – Will

+0

El compilador de C# genera un campo privado de "respaldo" con un nombre mutilado (para evitar colisionar con el nombre de cualquier otro campo que haya definido) para la propiedad automática. – Kit

1

Si agrega [DataMember] en private int m_SomeValue, este miembro no puede ser serializado, por lo que debe agregarse en público int SomeValue.

[DataMember]
private int m_SomeValue;

public int SomeValue { get {...} conjunto {...}}

el código de arriba no puede ser obtener valor en el cliente si lo utiliza a través de WCF.

+3

DataContractSerializers serializará cualquier campo privado que tenga el DataMemberAttribute en él. – rossisdead

+0

Estoy de acuerdo con rossisdead, cualquier campo privado tiene DataMemberattribute se serializa y queda expuesto por el servicio al cliente. – Niraj

6

Existen buenas razones para marcar campos en lugar de propiedades como DataMember.

Por favor marque esta para más detalles: http://blog.walteralmeida.com/2010/05/wcf-and-datacontract-serialization-internals-and-tips-.html

Por cierto: ContractSerializers serializarán cualquier campo privado que tiene el DataMemberAttribute en él sólo si se ejecuta en el entorno de plena confianza.No funciona en confianza parcial (marque el blog enumerados anteriormente para una solución)

4

Este decission depende del uso de un servicio WCF que:

  1. servicio interno consumida por usted administra sistemas .NET, que comparten las mismo modelo de dominio.
  2. Servicio externo consumido por diferentes plataformas, que no comparten el mismo modelo de dominio.

Caso 1.

serialización - es el proceso de persistir el estado del objeto. El estado del objeto en C# está representado por sus campos de datos.

Las propiedades en C# son esencialmente métodos que manipulan el estado del objeto. Su uso puede dar como resultado una deserialización diferente del estado del objeto, ya que el orden en que se establecen las propiedades puede tener un impacto en su estado de datos final. Otros factores pueden provocar una deserialización de estado incorrecta también, si, por ejemplo, el método (conjunto de propiedades) se basa en un contexto que está cambiando, como DateTime actual.

Usted puede decir ¿qué pasa con la encapsulación? No quiero que mi objeto esté en estado inválido, y debo hacer comprobaciones de validación, verificaciones de integridad del gráfico de objetos, etc. Sí, deberías, ¿así que ponemos los atributos de DataMember en puntales? No.

El problema aquí es que muchas personas mezclan dos cosas diferentes, DTO (objeto de transferencia de datos, contrato WCF) con la entidad de dominio. Lo que necesita es asegurarse de que los datos que recibe sean, en esencia, los mismos que se enviaron, y luego asegurarse de que puede construir una Entidad de dominio válida a partir de estos datos. La mejor manera de lograr esto es usar clases separadas para DTO, y construir una Entidad de dominio a partir de ellas.

Pero la mayoría de los programadores son flojos, y les gusta decorar de forma sencilla la entidad de dominio con los atributos de DataMemeber. En este caso, la decisión Campo o Prop depende de dónde está su lógica de validación; si su lógica de validación está oculta en los métodos Establecer, deberá usar los Apoyos, si es externo, debe usar Campos y validar su Entidad de dominio después de la desirialización.

P.S. Creo que las mismas reglas se aplican a cualquier proceso de serialización, como la persistencia de la base de datos.

Además, me gustaría mencionar que Silverlight no puede serializar \ deserializar campos privados, porque no puede acceder a ellos desde fuera mediante el uso de la reflexión, y deberá hacerlo privado y usar InternalsVisibleToAttribute.

Caso 2.

Este es uno duro. El enfoque principal aquí es la interoperabilidad. En el 99.9% tendrá clases separadas de DTO en este caso y lo más probable es que haya una gran cantidad de versiones diferentes para apoyar a clientes antiguos. No importa dónde coloque DataMembers attribs en esto, porque usa DTO's. No me molestaré en explicar este escenario, porque los desarrolladores que trabajan en un sistema de gran escala suelen tener bastante experiencia y no se molestan en leer SO.

+0

Cuando se trata de una serialización de tipo "bound-bound", ¡entonces sí! los campos realmente representan el estado. Estoy pensando en 'BinaryFormatter', etc. aquí. Sin embargo, en términos de una pieza de datos ** interoperable, donde el tipo de recepción es ** no ** idéntico (podría ser generado por mex/wsdl, o podría ser una plataforma completamente diferente), deberíamos tener ** ningún conocimiento ** de (o dependencia de) los campos. Sí, la validación sigue siendo importante, y existen mecanismos para eso (y otras cosas, como las devoluciones de llamada). –

+0

adicional; el trabajo de serialización es * no * simplemente "persistir el estado del objeto" - está haciendo eso * de la manera que coincide con el protocolo *. Para BinaryFormatter, eso significa (por defualt) "los campos", pero para WCF ... no tanto. ** datos ** no es 'm_someValue' - los * datos * son' SomeValue'. 'm_someValue' es un detalle de implementación. Hay formas de manejar el mapeo (como: usar 'Name' en el campo para hacer que' m_someValue' aparezca como 'SomeValue') –

+0

@MarcGravell Estoy de acuerdo con usted por parte de la interoperabilidad, estoy pensando en este tema como un proceso simple de estado persistente y restaurador, pero es más que eso. Mi respuesta básicamente se aplica solo a la situación cuando tienes C# en ambos extremos, y reutilizas las mismas clases. Si tomamos por ejemplo la situación cuando tenemos el código C# como receptor y el código PHP como remitente, entonces la situación es un poco diferente, necesito algo de tiempo para considerar esto, entonces creo que actualizaré mi respuesta. –

Cuestiones relacionadas