2009-06-24 12 views
7

Supponiamo che io ho il seguente (banalmente semplice) classe di base:Posso applicare un attributo a un membro ereditato?

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

Ora voglio fare quanto segue:

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

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

Ma senza realmente ridefinire la proprietà. Voglio applicare attributi ai membri della classe base. È possibile?

Il vero problema è che nel mio meccanismo di serializzazione da/a XML (che funziona brillantemente btw), trovo molti elementi simili in cui solo i nomi degli attributi differiscono (non sono coerenti, e io non t controllare il formato). In questo momento ho bisogno di creare una classe diversa per ogni elemento del genere, mentre sono uguali al 100% (a parte gli attributi).

Non credo sia possibile, ma potresti non saperlo mai.

UPDATE:

ho provato l'approccio di Marc, ma senza successo:

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(); 
    } 
} 

... non fa il trucco.

+0

Penso che tu intendessi ereditare da Semplice. – Noldorin

+0

Questo significa che un singolo file XML può contenere sia e elementi, che dovrebbero essere tutti serializzare a una classe il valore con una proprietà del valore? – Groo

+0

Dovrebbero serializzare sulla classe derivata, ovviamente, e il nome dell'elemento stesso dipende da dove è usato, ma sì, questa è l'idea generale. Inoltre, nella mia richiesta, è usato più comunemente per scrivere il codice XML piuttosto che leggerlo in –

risposta

3

Ho intenzione di rispondere a questa domanda me stesso, in modo che io possa accettare questa risposta. Non mi piace la risposta, ma suppongo sia l'unica risposta valida.

La risposta è: No, non puoi farlo.

2

Potrebbe forse utilizzare il costruttore di sovraccarico XmlSerializer che consente di passare gli attributi da applicare al runtime? Quindi non devi preoccuparti di questo ...

avvertenza: si desidera memorizzare nella cache l'istanza di serializzatore e riutilizzarla; in caso contrario (con i costruttori complessi) ogni volta genera generazione di tipo dinamico.

Esempio:

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); 
    } 
} 

uscita:

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

Anche se può funzionare, non mi consente di specificare l'override delle classi derivate. Quindi dovrei avere un serializzatore per ogni istanza in cui il nome dell'attributo è diverso, mentre tutti questi diversi elementi possono apparire nello stesso documento. –

0

si sono probabilmente consapevoli di questo, ma come idea (anche se la struttura del codice sarebbe cambiare completamente in quel caso):

Un modo sarebbe quello di serializzare la classe base come una raccolta di coppie nome-valore, usando la serializzazione personalizzata (c'è anche XDocument e altre cose utili per renderlo più semplice). Sebbene non imponga la sicurezza del tipo, ti eviterà di fare un sacco di lavoro manuale.

Preferisco anche passare alla serializzazione personalizzata perché consente una gamma più ampia di possibilità (serializzare classi immutabili, ad esempio). XmlSerializer è anche molto antipatico a volte (ad esempio, odio aggiungere la proprietà "MyFieldSpecified" per creare attributi facoltativi).

+0

Nella mia applicazione, ho un modello speciale solo per la generazione di XML. Ciò significa che abbiamo un "modello di dominio" e un "modello xml", e i due sono veramente separati. Ho deciso di utilizzare questo approccio per generare i nostri file XML utilizzando XmlWriter a causa della personalizzazione di XmlSerializer. Il nostro modello di dominio è serializzato utilizzando BinaryFormatter. –

0

Forse è possibile contrassegnare la proprietà della classe base con una mappatura comune, piuttosto che sostituire solo la proprietà nelle classi ereditate dove dovrebbe essere diversa. Almeno risparmieresti un po 'di override.

1

ne dite di questo:

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; } 
    } 
} 

Questa è la stessa tecnica usata per serializzare un tipo unserializable come un URI che richiede un tipo serializzabile nel costruttore.

+0

Stai ancora ridefinendo la proprietà. –

Problemi correlati