データ コントラクトの列挙型

列挙はデータ コントラクト モデルで表現できます。このトピックでは、いくつかの例を通してプログラミング モデルを説明します。

列挙の基本

データ コントラクト モデルで列挙型を使用する 1 つの方法として、DataContractAttribute 属性を型に割り当てる方法があります。この場合、データ コントラクトに含める必要のある各メンバに EnumMemberAttribute 属性を適用する必要があります。

2 つのクラスを次の例に示します。1 つ目は列挙を使用し、2 つ目は列挙を定義します。

Car クラスのインスタンスは、condition フィールドの値が NewUsedRental のいずれかに設定されている場合にのみ送受信できます。condition が、Broken または Stolen の場合、SerializationException がスローされます。

DataContractAttribute プロパティ (NameNamespace) を、列挙データ コントラクトとして通常通り使用できます。

列挙メンバ値

通常、データ コントラクトには、数値ではなく列挙メンバ名が含まれます。ただし、データ コントラクト モデルを使用しているときに、受信側が WCF クライアントである場合、エクスポートされたスキーマは数値を保持します。これは、XmlSerializer クラスの使用を使用している場合は、当てはまりません。

前の例では、conditionUsed に設定され、データが XML にシリアル化されると、結果の XML は <condition>Used</condition> になりますが <condition>1</condition> にはなりません。したがって、次のデータ コントラクトは、CarConditionEnum のデータ コントラクトと同じです。

たとえば、CarConditionEnum を送信側で使用し、CarConditionWithNumbers を受信側で使用できます。送信側で Used に値 "1" を使用し、受信側で値 "20" を使用しても、XML 表現は送信側と受信側共に <condition>Used</condition> です。

データ コントラクトに含めるには、EnumMemberAttribute 属性を適用する必要があります。.NET Framework では、列挙に特殊な値 0 (ゼロ) を常に割り当てることができます。これはまた、すべての列挙の既定値になります。ただし、この特殊値ゼロも EnumMemberAttribute 属性を使用してマークされない限りシリアル化できません。

これには、次のような 2 つの例外があります。

  • フラグ列挙体 (このトピックの後で説明)
  • EmitDefaultValue プロパティが false に設定された列挙データ メンバ (この場合、値がゼロの列挙はシリアル化されたデータから除外される)

列挙メンバ値のカスタマイズ

データ コントラクトの一部を形成する列挙メンバ値は、EnumMemberAttribute 属性の Value プロパティを使ってカスタマイズできます。

たとえば、次のデータ コントラクトは CarConditionEnum のデータ コントラクトとも等価です。

シリアル化されると、PreviouslyOwned の値には XML 表現 <condition>Used</condition> が含まれます。

単純な列挙

DataContractAttribute 属性が割り当てられていない列挙型をシリアル化することもできます。このような列挙型は、前の説明とまったく同じように扱われます。ただし、すべてのメンバ (NonSerializedAttribute 属性は適用されていない) に EnumMemberAttribute 属性が適用されているかのように扱われる点が異なります。たとえば、次の列挙は、前の CarConditionEnum の例と同じデータ コントラクトが暗黙的に含まれます。

列挙のデータ コントラクト名と名前空間、および列挙メンバ値をカスタマイズする必要がない場合に、単純な列挙を使用できます。

単純な列挙に関するメモ

EnumMemberAttribute 属性を単純な列挙に適用しても効力はありません。

SerializableAttribute 属性を列挙に適用してもしなくても変わりはありません。

DataContractSerializer クラスが、列挙メンバに適用された NonSerializedAttribute 属性を受け入れるという事実は、BinaryFormatterSoapFormatter の動作とは異なります。この 2 つのシリアライザは NonSerializedAttribute 属性を無視します。

フラグ列挙体

列挙体に FlagsAttribute 属性を適用できます。この場合、ゼロ個以上の列挙値のリストを同時に送受信できます。

これを行うには、DataContractAttribute 属性をフラグ列挙体に適用し、2 の累乗であるすべてのメンバを、EnumMemberAttribute 属性を使用してマークします。フラグ列挙体を使用するには、数列は (1、2、4、8、16、32、64 のように) 2 の累乗の連続である必要があります。

フラグの列挙値を送信する手順を次に示します。

  1. 数値にマップする列挙メンバ (EnumMemberAttribute 属性が適用されている) の検索を試みます。見つかった場合、そのメンバのみを含むリストを送信します。
  2. 合計の各部にマップされる列挙メンバ (それぞれに EnumMemberAttribute 属性が適用されている) が存在するような形で、数値をこの合計に分割します。このメンバすべてのリストを送信します。このような合計を見つけるために、最長一致アルゴリズムが使用されます。したがって、このような合計が存在したとしても見つかるとは限りません。この問題を回避するには、列挙メンバの数値を必ず 2 の累乗数にします。
  3. 前の 2 つの手順が失敗し、数値がゼロ以外の場合、SerializationException をスローします。数値がゼロの場合、空のリストを送信します。

フラグ操作で使用できる列挙の例を次に示します。

次の各値は、示されているようにシリアル化されます。

関連項目

リファレンス

DataContractSerializer

概念

データ コントラクトの使用
サービス コントラクトでのデータ転送の指定