2012-05-22 12 views
8

Sto utilizzando XMLSerializer per salvare questa classe in un file. La classe ha una stringa e un enum come mostrato di seguito:XmlSerializer: Come deserializzare un valore enum che non esiste più

public class IOPoint 
{ 
    string Name {get; set;} 
    TypeEnum {get; set;} 
} 


public enum TypeEnum 
{ 
    Temperature, 
    Pressure, 
    Humidity, 
} 

Quando serializzato è come questo.

<IOPoint> 
    <Name>Relative Humidity</Name> 
    <TypeEnum>Humidity</TypeEnum> 
</IOPoint> 

Ho serializzato e deserializzato questo oggetto senza problemi per diverse versioni. Non voglio più supportare l'umidità, quindi l'ho rimosso dall'enumerazione. Tuttavia, ciò provoca un'eccezione durante la deserializzazione da XML poiché il valore nel campo TypeEnum, Humidity, non è un valore valido per TypeEnum. Questo ha senso, ma come gestirlo?

Quello che mi piacerebbe fare è ignorare questo errore. E lascia il valore come null. Ho provato a implementare la classe OnUnknownElement XmlDeserilizationEvent. Sfortunatamente, questo non rileva questo errore.

Qualsiasi idea su come rilevare e ignorare questo errore (posso pulire dopo che la deserializzazione è completa).

Mitch

+0

Se hai trovato una soluzione mi piacerebbe sapere. Ho un problema correlato in cui il lato server include un nuovo valore di enum flag di cui il client non è a conoscenza, quindi voglio davvero trovare un modo per gestire la serializzazione di quel solo campo. La prossima volta userò solo un int, ma per ora ... la compatibilità a ritroso. – avenmore

risposta

5

È possibile contrassegnare il membro obsoleto

public enum TypeEnum 
{ 
    Temperature, 
    Pressure, 
    [Obsolete] 
    Humidity 
} 
+2

La ragione per cui non posso usare l'attributo [Obsoleto] è perché è pratica comune nel nostro codice iterare attraverso i valori enum. Quindi, anche se "Umidità" è contrassegnato come obsoleto, verrebbe comunque raccolto nei nostri loop foreach. (A meno che non ci sia un modo per sovrascrivere l'enumeratore?) – Mitch

+0

Puoi rendere la variabile nulla ovunque la usi? , ad esempio, TypeEnum?val = null; –

4

E 'generalmente considerata cattiva pratica di rimuovere un membro di enumerazione dopo la libreria è già in uso. Perché non lasci il membro in posizione, ma contrassegnalo con l'attributo [Obsolete] per impedire l'uso futuro? La specifica del secondo parametro del costruttore ObsoleteAttribute(string,bool) come true causerebbe un errore in fase di compilazione se si accede al membro contrassegnato.

public enum TypeEnum 
{ 
    Temperature, 
    Pressure, 

    [Obsolete("It's always sunny in Philadelphia", true)] 
    Humidity, 
} 

per aggirare l'errore quando il controllo dei valori deserializzate, si potrebbe confrontare con il valore sottostante: typeEnum == (TypeEnum)2.

1

È possibile implementare IXmlSerializable, dove è possibile utilizzare qualcosa come TryParse per l'enum.

Ma concordo con gli altri poster che utilizzano l'attributo Obsoleto.

+0

Se non riesco a trovare un'altra soluzione alternativa, la serializzazione personalizzata utilizzando IXMLSerializable è l'unica soluzione. Mentre ci sono, aggiungerei anche un campo Version che potrei usare per guidare la deserializzazione. Facciamo qualcosa di simile quando utilizziamo ISerializable. La vera classe ha circa 15 campi. Mi chiedo se potrei farla franca solo scrivendo il codice del deserializzatore per l'unico campo? – Mitch

2

È possibile utilizzare gli attributi per cambiare nomi dei nodi intorno e nascondere elementi di serializzazione XML, l'analisi solo che un elemento manualmente:

public class IOPoint 
{ 
public string Name {get; set;} 

[XmlIgnore] 
public TypeEnum TypeEnum {get; set;} 

[XmlElement("TypeEnum")] 
public string LegacyTypeEnum 
{ 
    get { return this.TypeEnum.ToString(); } 
    set 
    { 
    try 
    { 
    this.TypeEnum = (TypeEnum)Enum.Parse(typeof(TypeEnum),value); 
    } 
    catch(ArgumentException) 
    { 
    // Handle "Humidity" 
    } 
    catch(OverflowException) 
    { 
    } 
    } 
} 
} 

Per commenti sembra che vi sia una certa confusione; here is a worked example come progetto Visual Studio 2010. Questo approccio è un modo semplice di analizzare manualmente solo una proprietà di un oggetto (sfruttando ancora XmlSerializer per eseguire l'analisi XML).

+0

La serializzazione del valore enum come stringa invece dell'enumerazione, sarebbe una buona idea se non avessi già dei file XML che devo leggere. Questi file esistenti hanno l'elemento e devo ancora leggere il valore del campo TypeEnum e agire di conseguenza. Una soluzione ideale sarebbe quella di individuare l'eccezione quando tenta di deserializzare il valore di umidità. Ma nessuno dei gestori di eccezioni che hai inserito nel deserializzatore cattura questo errore. – Mitch

+0

Ho incluso un esempio compilabile per dimostrare che funziona e come funziona. – user423430

Problemi correlati