2012-05-22 16 views
8

Używam XMLSerializer do zapisania tej klasy do pliku. Klasa ma łańcuch i wyliczenie, jak pokazano poniżej:XmlSerializer: Jak odserializować wartość wyliczenia, która już nie istnieje

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


public enum TypeEnum 
{ 
    Temperature, 
    Pressure, 
    Humidity, 
} 

Po serializacji wygląda tak.

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

Serializuję i deserializuję ten obiekt bez problemów dla kilku wersji. Nie chcę już wspierać Wilgotności, więc usunąłem ją z enum. Powoduje to jednak wyjątek podczas deserializacji z XML, ponieważ wartość w polu TypeEnum, Humidity, nie jest poprawną wartością TypeEnum. Ma to sens, ale jak sobie z tym poradzić?

Co chcę zrobić, to po prostu zignorować ten błąd. I pozostaw wartość jako zero. Próbowałem już implementacji klasy OnUnknownElement XmlDeserilizationEvent. Niestety, nie łapie tego błędu.

Wszelkie pomysły dotyczące przechwytywania i ignorowania tego błędu (mogę wyczyścić po zakończeniu deserializacji).

Mitch

+0

Jeśli znalazłeś rozwiązanie, które chciałbym poznać. Mam podobny problem, gdy strona serwera zawiera nową wartość flagi wyliczeniowej, o której klient nie wie, więc naprawdę chcesz znaleźć sposób na zarządzanie serializacją tylko jednego pola. Następnym razem użyję tylko int, ale na razie ... kompatybilność wsteczna. – avenmore

Odpowiedz

5

Można oznaczyć element Przestarzałe

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

Powód, dla którego nie mogę użyć atrybutu [Przestarzały], jest to, że w naszym kodzie jest powszechna weryfikacja wartości wyliczeniowych. Więc nawet jeśli "Wilgotność" zostanie oznaczona jako przestarzała, nadal będzie ona odbierana w naszych pętlach foreach. (Chyba że istnieje sposób na przesłonięcie modułu wyliczającego?) – Mitch

+0

Czy możesz ustawić zmienną null w dowolnym miejscu, w której ją używasz? np. TypeEnum?val = null; –

4

Jest powszechnie uważany za złą praktyką, aby usunąć element wyliczenia po biblioteka jest już w użyciu. Dlaczego nie zostawisz członka w miejscu, ale oznaczysz go atrybutu [Obsolete], aby zapobiec przyszłym zastosowaniom? Określenie drugiego parametru konstruktora ObsoleteAttribute(string,bool) jako true spowoduje błąd kompilacji w przypadku dostępu do zaznaczonego elementu.

public enum TypeEnum 
{ 
    Temperature, 
    Pressure, 

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

Aby obejść ten błąd przy sprawdzaniu rozszeregować wartości, można porównać z wartością bazową: typeEnum == (TypeEnum)2.

1

Można wdrożyć IXmlSerializable, gdzie można użyć czegoś takiego jak TryParse do wyliczenia.

Ale zgadzam się z innymi plakatami, używając przestarzałego atrybutu.

+0

Jeśli nie mogę znaleźć innego rozwiązania, niestandardowe serializacji przy użyciu IXMLSerializable moje być jedynym rozwiązaniem. Będąc przy tym, dodałbym również pole wersji, które mógłbym użyć do kierowania deserializacją. Robimy coś podobnego podczas używania ISerializable. Prawdziwa klasa ma około 15 pól. Zastanawiam się, czy mógłbym uciec z tylko pisania kodu deserializera dla jednego pola? – Mitch

2

można wykorzystywać atrybuty wokół zmiany nazw węzłów i ukryć elementy z xml serializacji, analizowania tylko, że jeden element ręcznie:

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 Komentarze Nie wydaje się być pewne niejasności; here is a worked example jako projekt Visual Studio 2010. To podejście jest prostym sposobem ręcznego analizowania tylko jednej właściwości obiektu (nadal wykorzystującego XmlSerializer do wykonania analizy XML).

+0

Serializing wartość wyliczenia jako ciąg zamiast wyliczenia, byłoby dobrym pomysłem, jeśli nie mam już plików XML, które muszę przeczytać. Te istniejące pliki mają element i nadal muszę odczytać wartość pola TypeEnum i postępować zgodnie z nim. Idealnym rozwiązaniem byłoby złapanie wyjątku, gdy próbuje deserializować wartość wilgotności. Ale żaden z procedur obsługi wyjątków, które umieszczasz na deserializatorze, nie złapał tego błędu. – Mitch

+0

Dołączyłem próbkę kompilowaną, aby pokazać, że działa i jak działa. – user423430

Powiązane problemy