2009-06-24 13 views
7

Supongamos que tengo el siguiente (trivialmente sencilla) clase base:¿Puedo aplicar un atributo a un miembro heredado?

public class Simple 
{ 
    public string Value { get; set; } 
} 

ahora quiero hacer lo siguiente:

public class PathValue : Simple 
{ 
    [XmlAttribute("path")] 
    public string Value { get; set; } 
} 

public class ObjectValue : Simple 
{ 
    [XmlAttribute("object")] 
    public string Value { get; set; } 
} 

Pero sin llegar a la redefinición de la propiedad. Quiero aplicar atributos a los miembros de la clase base. es posible?

El problema real es que en mi mecanismo de serialización de/a XML (que funciona brillantemente por cierto), encuentro muchos elementos similares donde solo difieren los nombres de los atributos (no son consistentes, y no lo hago). t controlar el formato). Ahora mismo necesito crear una clase diferente para cada elemento, mientras que son como 100% iguales (aparte de los atributos).

No creo que sea posible, pero es posible que nunca lo sepas.

ACTUALIZACIÓN:

me trataron enfoque de Marc, pero fue en vano:

public class Document 
{ 
    public PathValue Path; 
    public ObjectValue Object; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var doc = new Document() 
     { 
      Path = new PathValue() { Value = "some path" }, 
      Object = new ObjectValue() { Value = "some object" } 
     }; 

     XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 

     overrides.Add(typeof(PathValue), "Value", new XmlAttributes() { XmlAttribute = new XmlAttributeAttribute("path") }); 
     overrides.Add(typeof(ObjectValue), "Value", new XmlAttributes() { XmlAttribute = new XmlAttributeAttribute("object") }); 

     XmlSerializer serializer = new XmlSerializer(typeof(Document), overrides); 

     serializer.Serialize(Console.Out, doc); 

     Console.WriteLine(); 
     Console.ReadLine(); 
    } 
} 

... no hace el truco.

+0

Creo que quisiste heredar de Simple. – Noldorin

+0

¿Esto significa que un único archivo xml puede contener elementos de y , que deberían serializarse en una clase de valor con una propiedad de valor? – Groo

+0

Deben serializarse a la clase derivada, obviamente, y el nombre del elemento depende de dónde se usa, pero sí, esa es la idea general. Además, en mi aplicación, se usa más comúnmente para escribir el XML que para leerlo. –

Respuesta

3

Voy a responder esta pregunta yo mismo, para que pueda aceptar esta respuesta. No me gusta la respuesta, pero supongo que es la única respuesta válida.

La respuesta es: No, no puede hacerlo.

2

¿Podría quizás usar el constructor sobrecarga XmlSerializer que le permite pasar los atributos para aplicar en tiempo de ejecución? Entonces no tiene que preocuparse por eso ...

advertencia: desea almacenar en caché la instancia del serializador y volver a utilizarla; de lo contrario (con los constructores complejos) genera generación dinámica de tipo cada vez.

Ejemplo:

using System; 
using System.Xml.Serialization; 
public class Simple { 
    public string Value { get; set; } 

    static void Main() { 
     XmlAttributeOverrides overrides = new XmlAttributeOverrides(); 
     overrides.Add(typeof(Simple), "Value", new XmlAttributes { 
      XmlAttribute = new XmlAttributeAttribute("path") 
     }); 
     XmlSerializer pathSerializer = new XmlSerializer(
      typeof(Simple), overrides); 
     // cache and re-use pathSerializer!!! 

     Simple obj = new Simple(); 
     obj.Value = "abc"; 
     pathSerializer.Serialize(Console.Out, obj); 
    } 
} 

Salida:

<Simple xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:xsd="http://www.w3.org/2001/XMLSchema" path="abc" /> 
+0

Si bien eso puede funcionar, no me permite especificar la anulación en las clases derivadas. Entonces, debería tener un serializador para cada instancia en la que el nombre del atributo sea diferente, mientras que todos estos elementos diferentes pueden aparecer en el mismo documento. –

0

usted está probablemente consciente de esto, pero como una idea (aunque la estructura del código cambiaría por completo en ese caso):

Una forma sería serializar la clase base como una colección de pares nombre-valor, utilizando una serialización personalizada (también hay XDocument y cosas útiles similares para facilitarlo). A pesar de que no impone la seguridad de tipo, le evitaría hacer mucho trabajo manual.

También prefiero ir a la serialización personalizada porque permite un rango más amplio de posibilidades (serialización de clases inmutables, por ejemplo). XmlSerializer también es realmente desagradable a veces (por ejemplo, odio agregar la propiedad "MyFieldSpecified" para crear atributos opcionales).

+0

En mi aplicación, tengo un modelo especial solo para la generación de XML. Eso significa que tenemos un "modelo de dominio" y un "modelo xml", y los dos están realmente separados. Decidí usar este enfoque para generar nuestros archivos XML sobre el uso de XmlWriter debido a la personalización de XmlSerializer. Nuestro modelo de dominio se serializa utilizando BinaryFormatter. –

0

Quizás pueda marcar la propiedad de la clase base con un mapeo común, que solo anula la propiedad en clases heredadas donde debería ser diferente. Al menos, ahorrarías algo de prioridad.

1

¿Qué tal esto:

public class Simple 
{ 
    [XmlIgnore] 
    public string Value { get; set; } 
} 

public class PathValue : Simple 
{ 
    [XmlAttribute("path")] 
    public string Path { 
      get { return base.Value != null ? base.Value : null; } 
      set { base.Value = value != null ? value : null; } 
    } 
} 

public class ObjectValue : Simple 
{ 
    [XmlAttribute("object")] 
    public string Object { 
      get { return base.Value != null ? base.Value : null; } 
      set { base.Value = value != null ? value : null; } 
    } 
} 

Ésta es la misma técnica que se utiliza para serializar un tipo unserializable como un URI que toma un tipo serializable en el constructor.

+0

Aún está redefiniendo la propiedad. –

Cuestiones relacionadas