2010-02-24 13 views
85

tengo alguna clase que estoy pasando como resultado de un método de servicio, y que la clase tiene un encuentro única propiedad:WCF se ahoga en propiedades sin "conjunto". Cualquier solución?

[DataContract] 
public class ErrorBase 
{ 
    [DataMember] 
    public virtual string Message { get { return ""; } } 
} 

Estoy recibiendo una excepción en el lado del servicio:

System.Runtime.Serialization.InvalidDataContractException: no se estableció el método para la propiedad 'Mensaje' en el tipo 'MyNamespace.ErrorBase'.

Tengo que tener esta propiedad como único getter, no puedo permitir que los usuarios le asignen un valor. ¿Alguna solución alternativa que podría usar? ¿O me falta algún atributo adicional?

Respuesta

93

Dale un captador mensaje público, pero colocador protegida, por lo que sólo subclases (y DataContractSerializer, porque engaña :) pueden modificar el valor.

+1

¡En realidad, funciona mejor en mi caso! ¡Gracias! – Andrey

+0

¡Esa es una buena solución! – Russell

+0

¡Gracias, me alegro de que haya sido útil!En realidad, este es solo uno de varios usos para este truco. Como getters y setters son técnicamente funciones, también puede usar esta misma técnica para proporcionar serialización personalizada de tipos primitivos (quizás un formato de tiempo personalizado en XML) sin necesidad de utilizar el intimidante IDataContractSurrogate. –

12

Incluso si no necesita actualizar el valor, el setter es utilizado por WCFSerializer para deserializar el objeto (y restablecer el valor).

esto es así lo que está buscando: WCF DataContracts

+1

¿De modo que la única forma de superar el problema es convertirlo en un método en lugar de en una propiedad? De nuevo, no puedo permitir "establecer" en esta propiedad – Andrey

+0

. Podría hacer que sea un método (por ejemplo, GetMessage() {return "";}) alternativamente, estoy bastante seguro de que podría decirle al Serializador WCF que lo ignore. Veré lo que puedo encontrar y te lo haré saber. – Russell

+1

Esta pregunta de stackoverflow da en el clavo: http://stackoverflow.com/questions/172681/wcf-datacontracts – Russell

3

¿No podría simplemente tener un colocador de "no hacer nada"?

[DataContract] 
public class ErrorBase 
{ 
    [DataMember] 
    public virtual string Message 
    { 
     get { return ""; } 
     set { } 
    } 
} 

¿O también el serializador Barf de DataContract en eso?

+13

No barf, simplemente no quería que los desarrolladores que usan la API del cliente piensen que pueden asignar cosas a la propiedad. – Andrey

2

Las propiedades con el atributo DataMember siempre requieren establecerse. Debería volver a escribir un objeto similar en la aplicación cliente ya que a los miembros de DataContract siempre se les pueden asignar valores.

2

Tuve este problema con ASP.NET MVC y el deseo de utilizar DataContractSerializer para poder controlar los nombres en los elementos en la salida JSON. Eventualmente cambié el serializador a JSON.NET, que admite propiedades sin setters (que DataContractSerializer no) y control de nombre de propiedad (que el serializador JSON integrado en ASP.NET MVC no) a través de [JsonProperty(PropertyName = "myName")].

2

Si se trata de una opción viable, entonces, en lugar de tener ErrorBase como la clase base, lo definen como sigue:

public interface IError 
    { 
     string Message 
     { 
      [OperationContract] 
      get; 

      // leave unattributed 
      set; 
     } 
    } 

Ahora, a pesar de que existe un organismo, que es inaccesible para el cliente a través del canal de WCF, por lo es como si fuera privado.

7
[DataMember(Name = "PropertyName")] 
public string PropertyName 
{ 
    get 
    { 
     return ""; 
    } 
    private set 
    { } 
} 
5

Si solo tiene un captador, ¿por qué necesita serializar la propiedad en absoluto? Parece que podría eliminar el atributo DataMember para la propiedad de solo lectura, y el serializador simplemente ignoraría la propiedad.

+2

Efectivamente, no tiene sentido serializar una propiedad derivada (por ejemplo, una propiedad de URL que se calcula desde una propiedad de ID) a un almacenamiento persistente (por ejemplo, una base de datos) - upvote para eso - pero tiene sentido serializarlo para una representación (por ejemplo, JSON o XML) que es devuelta por una solicitud API. –

Cuestiones relacionadas