2012-05-22 17 views
8

XMLSerializerを使用してこのクラスをファイルに保存しています。クラスは以下のように文字列と列挙型を持っています。XmlSerializer:存在しなくなった列挙値を逆シリアル化する方法

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


public enum TypeEnum 
{ 
    Temperature, 
    Pressure, 
    Humidity, 
} 

シリアル化すると、このようになります。

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

私はこのオブジェクトをいくつかのバージョンで問題なくシリアル化およびデシリアライズしてきました。私はもはや湿度をサポートしたくないので、enumからそれを削除しました。ただし、TypeEnumフィールドの値HumidityがTypeEnumの有効な値ではないため、XMLからデシリアライズするときに例外が発生します。これは理にかなっていますが、これをどのように処理するのですか?

私がしたいのは、このエラーを無視するだけです。値をnullのままにします。私はOnUnknownElement XmlDeserilizationEventクラスを実装しようとしました。残念ながら、このエラーは発生しません。

このエラーをキャッチして無視する方法については、アイデアがありません(デシリアライズが完了したら削除できます)。

ミッチは

+0

あなたが知りたい解決策を見つけた場合は、私は、クライアントが知らない新しいenumフラグ値をサーバーサイドに含めているので、実際にはそのフィールドのシリアル化を管理する方法を見つけたいという、関連する問題があります。次回はintを使っていますが、今は... backward互換です。 – avenmore

答えて

5

あなたはあなたのライブラリがすでに使用されている後にそれは一般的に列挙メンバーを削除するには悪い習慣と考えられています

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

[廃止]属性を使用できないのは、コードでenum値を反復処理するのが一般的なためです。したがって、たとえ "湿度"が廃止とマークされていても、foreachループではまだ取り出されます。 (列挙子をオーバーライドする方法がない限り) – Mitch

+0

変数を使用しているときはいつでも変数をnullにできますか?例えば、TypeEnum? val = null; –

4

廃止されたメンバーをマークすることができます。あなたはメンバーをその場所に残しておき、将来の使用を防ぐために[Obsolete]という属性を付けるのはなぜですか? ObsoleteAttribute(string,bool)コンストラクタの2番目のパラメータをtrueと指定すると、マークされたメンバにアクセスするとコンパイル時エラーが発生します。 typeEnum == (TypeEnum)2:非直列化された値をチェックするとき、あなたは根本的な値と比較可能性のエラーを回避するために

public enum TypeEnum 
{ 
    Temperature, 
    Pressure, 

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

1

IXmlSerializableを実装できます。ここでは、TryParseなどの列挙型を使用できます。

しかし、私はObsolete属性を使用している他のポスターに同意します。

+0

別の回避策が見つからない場合は、IXMLSerializableを使用したカスタムシリアル化が唯一の解決策になります。私はそれに慣れている間に、私はバージョンフィールドを追加して、私が非直列化を導くために使用できるようにします。 ISerializableを使用するときも同様のことを行います。実際のクラスには約15のフィールドがあります。 1つのフィールドのデシリアライザコードを書いてしまうのではないかと思いますか? – Mitch

2

手動でただ1つの要素を解析し、周りのノード名を変更し、XMLシリアル化の要素を非表示にする属性を使用することができます。

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

パーは、いくつかの混乱があるように見えるコメント。 here is a worked exampleをVisual Studio 2010プロジェクトとして追加します。この方法は、オブジェクトの1つのプロパティだけを手動で解析する簡単な方法です(XmlSerializerを利用してXML解析を行う)。

+0

列挙型ではなく文字列として列挙型の値をシリアライズすることは、読み込みが必要なXMLファイルがまだない場合には便利です。これらの既存のファイルはの要素を持っていますが、それでもTypeEnumフィールドの値を読み取り、それに応じて動作する必要があります。理想的な解決策は、湿度の値を逆直列化しようとするときに例外をキャッチすることです。しかし、デシリアライザに置いた例外ハンドラのどれもがこのエラーをキャッチしません。 – Mitch

+0

私はコンパイル可能なサンプルを用意して、そのサンプルが機能し、動作することを実証しました。 – user423430

関連する問題