2009-02-26 17 views
10

Estoy tratando de encontrar una manera de cambiar el comportamiento de serialización de una propiedad.Reemplazando una propiedad con un atributo

Digamos que tengo una situación como esta:

[Serializable] 
public class Record 
{ 
    public DateTime LastUpdated {get; set; } 

    // other useful properties ... 
} 

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 

    // other useful properties ... 
} 

Ahora quiero serializar EmployeeRecord. No quiero serializar la propiedad LastUpdated de la clase Record. (Sin embargo, quiero que LastUpdated sea serializado cuando serializo Record).

principio traté de ocultar la propiedad LastUpdated mediante el uso de la palabra clave nueva y luego añadir el atributo XmlIgnore:

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 

    [XmlIgnore] 
    public new DateTime LastUpdated {get; set; } 
    // other useful properties ... 
} 

Pero eso no funcionó. Luego he intentado hacer la base LastUpdated virtual y anulando, manteniendo el atributo:

[Serializable] 
public class Record 
{ 
    public virtual DateTime LastUpdated {get; set; } 

    // other useful properties ... 
} 

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 

    [XmlIgnore] 
    public override DateTime LastUpdated {get; set; } 
    // other useful properties ... 
} 

Esto no funcionó bien. En ambos intentos, LastUpdated ignoró el atributo XmlIgnore y felizmente se dedicó a la serialización.

¿Hay alguna manera de hacer que lo que intento hacer ocurra?

+0

¿Cómo lo serializas? Porque si usas la serialización binaria, el atributo XmlIgnore no servirá de mucho. –

+0

Estoy usando XmlSerializer –

+0

Utilizaría el atributo NonSerialized para la serialización binaria. – snarf

Respuesta

17

Primero, el [serializable] attr no tiene nada que ver con el XmlSerializer. Esa es una pista falsa. [Serializable] es significativo para System.Runtime.Serialization, mientras que XmlSerializer reside en System.Xml.Serialization. Si está decorando su clase con [Serializable] y sus miembros con [XmlIgnore], probablemente se esté confundiendo usted u otros lectores de su código.

Xml La serialización en .NET es muy flexible. Dependiendo de cómo se realice la serialización, directamente por usted o indirectamente, digamos por el tiempo de ejecución de los servicios web, tiene diferentes formas de controlar las cosas.

Una opción es utilizar propertyName Patrón especificado para activar o desactivar la propiedad en serialización XML. Suponga que tiene este código:

public class TypeA 
{ 
    public DateTime LastModified; 
    [XmlIgnore] 
    public bool LastModifiedSpecified; 
} 

Entonces, si LastModifiedSpecified es falsa en un caso, el campo LastModified no será serializado para esa instancia. En el constructor para su tipo, puede establecer que LastModifiedSpecified siempre sea verdadero en el tipo base, y siempre falso en el tipo derivado. El booleano real - LastModifiedSpecified - nunca se serializa porque está marcado XmlIgnore.

Este pequeño truco está documentado here.

Su otra opción es utilizar XmlAttributeOverrides, que es una manera de proporcionar de forma dinámica el conjunto de atributos de serialización XML (como XmlElementAttribute, XmlIgnoreAttribute, XmlRootAttribute, y así sucesivamente ...) - proporcionando dinámicamente esos atributos al serializador en tiempo de ejecución . El XmlSerializer, en lugar de inspeccionar el tipo en sí mismo para esos atributos, simplemente recorrerá la lista de atributos de reemplazo proporcionados a su constructor.

var overrides = new XmlAttributeOverrides(); 
    // ....fill the overrides here.... 
    // create a new instance of the serializer specifying overrides 
    var s1 = new XmlSerializer(typeof(Foo), overrides); 
    // serialize as normal, here. 

Esto se ilustra en más detalle here.

En su caso, debe proporcionar un XmlIgnoreAttribute como una anulación, pero solo al serializar el tipo derivado.(o lo que sea) Esto solo funciona cuando crea una instancia directa de XmlSerializer; no funcionará cuando la serialización se realice implícitamente por el tiempo de ejecución, como ocurre con los servicios web.

¡Salud!

+0

Guau, nunca antes había oído hablar del patrón especificado. ¡Trabajado como un encanto! –

8

Lo mejor que se me ocurre ...

[Serializable] 
public class Record 
{ 
    public DateTime LastUpdated {get; set; } 
    public virtual bool ShouldSerializeLastUpdated() {return true;} 
    // other useful properties ... 
} 

public class EmployeeRecord : Record 
{ 
    public string EmployeeName {get; set; } 
    public override bool ShouldSerializeLastUpdated() {return false;} 
    // other useful properties ... 
} 

Básicamente, hay algunos patrones que XmlSerializer aspectos; public bool ShouldSerialize*() y public bool *Specified {get;set;} (tenga en cuenta que también debe marcar *Specified con [XmlIgnore] ...).

No muy elegante, lo concederé; pero XmlSerializer solo mira a los miembros públicos, por lo que ni siquiera puede ocultarlos (excepto [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]).

Cuestiones relacionadas