2009-09-26 16 views
7

Estoy experimentando con los servicios web RESTful de WCF y tengo un problema con las propiedades implementadas automáticamente.Serialización de WCF Xml y propiedades autoempleadas

tengo una clase llamada DeviceDescriptor, que se define de la siguiente manera:

public class DeviceDescriptor 
{ 
    public string DeviceId { get; set; } 
    public string DisplayName { get; set; } 
} 

Tengo un servicio de WCF REST que se supone que devolver una lista de DeviceDescriptors - aquí está mi contrato de servicios:

[ServiceContract] 
public interface IChooser 
{ 
[WebGet(UriTemplate="/Chooser/RegisteredDevices")] 
[OperationContract] 
List<DeviceDescriptor> RegisteredDevices(); 

[WebGet(UriTemplate = "/Chooser/Ping")] 
[OperationContract] 
string Ping(); 
} 

Bueno, funciona, excepto que en el resultado XML, los nombres de las propiedades no salen bien, parece que el serializador usa los "nombres indetectables" de los campos de respaldo generados automáticamente en lugar de los nombres de las propiedades. Mi salida sale así:

<DeviceDescriptor> 
    <_x003C_DeviceId_x003E_k__BackingField>Pipe.Dome</_x003C_DeviceId_x003E_k__BackingField> 
    <_x003C_DisplayName_x003E_k__BackingField>Pipe diagnostic tool</_x003C_DisplayName_x003E_k__BackingField> 
</DeviceDescriptor> 

Por lo tanto, hay una manera de salir de esto? ¿Por qué doesn; t WCF usa los nombres de las propiedades?

+0

La paradoja Stackoverflow: Me acabo de ganar la insignia 'pregunta popular' por este concepto, sin embargo, sólo hay una upvote. –

Respuesta

4

Utiliza la reflexión para obtenerlos IIRC, si quieres más control debes intentar utilizar un DataContract, te permite especificar los nombres exactos (usando [DataMember(Name = "DeviceID")]). Consulte también la documentación en DataMemberAttribute

+0

Eso lo hizo. Tuve que poner un atributo [DataContract] en la clase y luego [DataMember (Name = "xxx")] atributos en las propiedades, shazamm. Aunque es un poco apestoso.Me pregunto por qué WCF encuentra los campos de respaldo supuestamente privados implementados automáticamente y los utiliza en lugar de los nombres de propiedad pública. El compilador de C# debe estar haciendo una generación de código dudosa. –

+0

Como dije, probablemente usa la reflexión para obtener la ubicación donde se almacena el valor de la propiedad, no el nombre de la propiedad en sí; pero no soy un experto en WCF, así que tal vez debas hacerte una pregunta sobre cómo WCF realmente descubre los nombres;) – Anteru

+0

(has respondido completamente la pregunta principal, pero para dar seguimiento a los comentarios, los toco brevemente en los puntos a continuación) –

9

Para agregar algunos detalles a la pregunta que hace en los comentarios ... en los buenos viejos (3.0) días WCF/DataContractSerializer era bastante estricto. Si su tipo no se marcó explícitamente como [DataContract] (o IXmlSerializable para la reserva), entonces no se serializaría. Usó los miembros marcados como [DataMember], utilizando el nombre explícito en el atributo si se especifica, o el nombre del miembro en caso contrario. La vida fue buena.

Más recientemente, el código fue cambiado permitiendo que los tipos "regulares" sean serializados, es decir, aquellos sin contratos de datos. Lo hace utilizando el mismo enfoque que usa BinaryFormatter, es decir, funciona en el campo -level. Esta es la OMI malo:

  • campos son la aplicación, no el contrato
  • es frágil si cambia ... nada!
  • que no tiene mucho agua contra la ofuscación
  • algo tan inocente como interruptor a/desde un auto-prop romperlo (auto-props han nombres de campo verdaderamente extrañas, que no pueden ser emulado en regular de C#)

sé qué esta era tentador (para permitir WCF para el transporte de tipos arbitrarios), pero cada tendón en mi cuerpo dice que esto era una pérdida neta. Es mucho mejor hacer que las personas usen las herramientas correctas (contratos de datos) que dejar que sus clases rotas funcionen. En el original 3.0, habría habido una excepción lanzada diciendo cómo solucionar esto correctamente: márquelo como [DataContract] y dígale qué [DataMember] s desea serializar.

Consulte también: Obfuscation, serialization and automatically implemented properties

+0

Tengo que estar de acuerdo con usted: no solo este cambio es malo en la práctica sino que "se siente" mal, ya que va en contra de la filosofía de aceptación que ha estado presente durante tanto tiempo. –