Enumerationstypen in Datenverträgen
Enumerationen können im Datenvertragsmodell ausgedrückt werden. In diesem Thema werden mehrere Beispiele behandelt, in denen das Programmiermodell erklärt wird.
Grundlagen der Enumeration
Eine Möglichkeit, Enumerationstypen im Datenvertragmodell zu verwenden, besteht darin, das DataContractAttribute-Attribut auf den Typ anzuwenden. Anschließend müssen Sie das EnumMemberAttribute-Attribut auf jeden Member anwenden, der im Datenvertrag enthalten sein soll.
Das folgende Beispiel zeigt zwei Klassen. Die erste Klasse verwendet die Enumeration, und die zweite Klasse definiert die Enumeration.
<DataContract()> _
Public Class Car
<DataMember()> _
Public model As String
<DataMember()> _
Public condition As CarConditionEnum
End Class
<DataContract(Name := "CarCondition")> _
Public Enum CarConditionEnum
<EnumMember> NewCar
<EnumMember> Used
<EnumMember> Rental
Broken
Stolen
End Enum
[DataContract]
public class Car
{
[DataMember]
public string model;
[DataMember]
public CarConditionEnum condition;
}
[DataContract(Name = "CarCondition")]
public enum CarConditionEnum
{
[EnumMember]
New,
[EnumMember]
Used,
[EnumMember]
Rental,
Broken,
Stolen
}
Sie können eine Instanz der Car
-Klasse nur senden oder empfangen, wenn das Feld condition
auf einen der folgenden Werte festgelegt ist: New
, Used
oder Rental
. Wenn condition
den Wert Broken
oder Stolen
hat, wird eine SerializationException ausgelöst.
Sie können die DataContractAttribute-Eigenschaften (Name und Namespace) wie gewohnt für Enumerationsdatenverträge verwenden.
Enumerationsmemberwerte
Im Allgemeinen enthält der Datenvertrag Enumerationsmembernamen, keine numerischen Werte. Wenn Sie jedoch das Datenvertragsmodell verwenden, werden die numerischen Werte im exportierten Schema beibehalten, wenn es sich bei der empfangenden Stelle um einen WCF-Client handelt. Beachten Sie, dass dies nicht der Fall ist, wenn Sie das Verwenden der XmlSerializer-Klasse verwenden.
Wenn im obigen Beispiel condition
auf Used
festgelegt ist und die Daten in XML serialisiert werden, lautet das XML-Ergebnis <condition>Used</condition>``<condition>1</condition>
, und nicht . Deshalb entspricht der folgende Datenvertrag dem Datenvertrag von CarConditionEnum
.
<DataContract(Name := "CarCondition")> _
Public Enum CarConditionWithNumbers
<EnumMember> NewCar = 10
<EnumMember> Used = 20
<EnumMember> Rental = 30
End Enum
[DataContract(Name = "CarCondition")]
public enum CarConditionWithNumbers
{
[EnumMember]
New = 10,
[EnumMember]
Used = 20,
[EnumMember]
Rental = 30,
}
Sie können beispielsweise CarConditionEnum
auf der Absenderseite und CarConditionWithNumbers
auf der Empfängerseite verwenden. Obwohl die Absenderseite den Wert 1 und die Empfängerseite den Wert 20 für Used
verwendet, lautet die XML-Darstellung für beide Seiten <condition>Used</condition>
.
Um das Einbinden in den Datenvertrag zu erreichen, müssen Sie das EnumMemberAttribute-Attribut anwenden. Unter .NET Framework können Sie immer den Sonderwert 0 (Null) auf eine Enumeration anwenden. Dabei handelt es sich auch um den Standardwert für Enumerationen. Auch dieser Sonderwert 0 kann jedoch nur serialisiert werden, wenn er mithilfe des EnumMemberAttribute-Attributs gekennzeichnet ist.
Dabei gelten zwei Ausnahmen:
Flagenumerationen (weiter unten in diesem Thema beschrieben).
Enumerationsdatenmember, für die die EmitDefaultValue-Eigenschaft auf false festgelegt ist. (In diesem Fall wird die Enumeration mit dem Wert "0" einfach aus den serialisierten Daten weggelassen.)
Anpassen von Enumerationsmemberwerten
Sie können den Enumerationsmemberwert anpassen, der Teil des Datenvertrags ist, indem Sie die Value-Eigenschaft des EnumMemberAttribute-Attributs verwenden.
Der folgende Datenvertrag entspricht auch dem Datenvertrag von CarConditionEnum
.
<DataContract(Name := "CarCondition")> _
Public Enum CarConditionWithDifferentNames
<EnumMember(Value := "New")> BrandNew
<EnumMember(Value := "Used")>PreviouslyOwned
<EnumMember> Rental
End Enum
[DataContract(Name = "CarCondition")]
public enum CarConditionWithDifferentNames
{
[EnumMember(Value = "New")]
BrandNew,
[EnumMember(Value = "Used")]
PreviouslyOwned,
[EnumMember]
Rental
}
Nach der Serialisierung weist der Wert von PreviouslyOwned
die XML-Darstellung <condition>Used</condition>
auf.
Einfache Enumerationen
Sie können auch Enumerationstypen serialisieren, auf die das DataContractAttribute-Attribut nicht angewendet wurde. Enumerationstypen dieser Art werden exakt wie zuvor beschrieben behandelt. Es gilt jedoch die Ausnahme, dass jeder Member (auf den das NonSerializedAttribute-Attribut nicht angewendet wurde) so behandelt wird, als ob das EnumMemberAttribute-Attribut angewendet wurde. Zum Beispiel verfügt die folgende Enumeration implizit über einen Datenvertrag, der dem Datenvertrag im vorherigen CarConditionEnum
-Beispiel entspricht.
Public Enum CarCondition
[New]
Used
Rental
End Enum
public enum CarCondition
{
New,
Used,
Rental,
[NonSerialized]
Lost
}
Sie können einfache Enumerationen verwenden, wenn es nicht erforderlich ist, den Datenvertragsnamen und den Namespace der Enumeration und die Enumerationsmemberwerte anzupassen.
Hinweise zu einfachen Enumerationen
Wenn Sie das EnumMemberAttribute-Attribut auf einfache Enumerationen anwenden, hat dies keine Auswirkung.
Es ist unerheblich, ob Sie das SerializableAttribute-Attribut auf die Enumeration anwenden.
Die Tatsache, dass die DataContractSerializer-Klasse das NonSerializedAttribute-Attribut berücksichtigt, das auf Enumerationsmember angewendet wird, gilt nicht für das Verhalten von BinaryFormatter und SoapFormatter. Beide Serialisierungsprogramme ignorieren das NonSerializedAttribute-Attribut.
Flagenumerationen
Sie können das FlagsAttribute-Attribut auf Enumerationen anwenden. In diesem Fall kann eine Liste von null oder mehr Enumerationswerten gleichzeitig gesendet oder empfangen werden.
Wenden Sie dazu das DataContractAttribute-Attribut auf die Flagenumeration an, und markieren Sie dann alle Member, die Potenzen von 2 sind, mit dem EnumMemberAttribute-Attribut. Beachten Sie, dass es sich bei der Progression um eine ununterbrochene Folge mit Potenzen des Werts 2 handeln muss (beispielsweise 1, 2, 4, 8, 16, 32, 64).
Die folgenden Schritte gelten für das Senden des Enumerationswerts eines Flags:
Versuchen Sie, einen Enumerationsmember zu finden (mit angewendetem EnumMemberAttribute-Attribut), der dem numerischen Wert zugeordnet ist. Wenn Sie einen Member finden, senden Sie eine Liste, die nur diesen Member enthält.
Versuchen Sie, den numerischen Wert so zu einer Summe aufzulösen, dass Enumerationsmember vorhanden sind (jeweils mit angewendetem EnumMemberAttribute-Attribut), die den einzelnen Teilen der Summe zugeordnet sind. Senden Sie die Liste mit allen Membern dieser Art. Beachten Sie, dass zum Auffinden einer solchen Summe der gierige Algorithmus verwendet wird. Daher ist nicht garantiert, dass eine Summe gefunden wird, auch wenn eine Summe vorhanden ist. Um dieses Problem zu verhindern, sollten Sie sicherstellen, dass es sich bei den numerischen Werten der Enumerationsmember um Potenzen von 2 handelt.
Lösen Sie eine SerializationException aus, wenn die vorausgehenden zwei Schritte fehlschlagen und der numerische Wert ungleich 0 ist. Senden Sie die leere Liste, wenn der numerische Wert 0 ist.
Beispiel
Das folgende Enumerationsbeispiel kann für einen Flagvorgang verwendet werden.
<DataContract(), Flags()> _
Public Enum CarFeatures
None = 0
<EnumMember> AirConditioner = 1
<EnumMember> AutomaticTransmission = 2
<EnumMember> PowerDoors = 4
AlloyWheels = 8
DeluxePackage = AirConditioner Or AutomaticTransmission Or PowerDoors Or AlloyWheels
<EnumMember> CDPlayer = 16
<EnumMember> TapePlayer = 32
MusicPackage = CDPlayer Or TapePlayer
<EnumMember>Everything = DeluxePackage Or MusicPackage
End Enum
[DataContract][Flags]
public enum CarFeatures
{
None = 0,
[EnumMember]
AirConditioner = 1,
[EnumMember]
AutomaticTransmission = 2,
[EnumMember]
PowerDoors = 4,
AlloyWheels = 8,
DeluxePackage = AirConditioner | AutomaticTransmission | PowerDoors | AlloyWheels,
[EnumMember]
CDPlayer = 16,
[EnumMember]
TapePlayer = 32,
MusicPackage = CDPlayer | TapePlayer,
[EnumMember]
Everything = DeluxePackage | MusicPackage
}
Die folgenden Beispielwerte werden dabei wie angegeben serialisiert.
Private cf1 As CarFeatures = CarFeatures.AutomaticTransmission
'Serialized as <cf1>AutomaticTransmission</cf1>
Private cf2 As CarFeatures = ctype(5,CarFeatures)
'Serialized as <cf2>AirConditioner PowerDoors</cf2> since 5=1+4
Private cf3 As CarFeatures = CarFeatures.MusicPackage
'Serialized as <cf3>CDPlayer TapePlayer</cf3> since MusicPackage
' itself is not an EnumMember.
Private cf4 As CarFeatures = CarFeatures.Everything
'Serialized as <cf4>Everything</cf4> since Everything itself is an EnumMember.
Private cf5 As CarFeatures = CarFeatures.DeluxePackage
'Throws a SerializationException since neither DeluxePackage nor
' AlloyWheels are EnumMembers.
Private cf6 As CarFeatures = CarFeatures.None
'Serialized as the empty list <cf6></cf6> since there is no EnumMember mapped to zero.
CarFeatures cf1 = CarFeatures.AutomaticTransmission;
//Serialized as <cf1>AutomaticTransmission</cf1>
CarFeatures cf2 = (CarFeatures)5;
//Serialized as <cf2>AirConditioner PowerDoors</cf2> since 5=1+4
CarFeatures cf3 = CarFeatures.MusicPackage;
//Serialized as <cf3>CDPlayer TapePlayer</cf3> since MusicPackage itself is not an EnumMember
CarFeatures cf4 = CarFeatures.Everything;
//Serialized as <cf4>Everything</cf4> since Everything itself is an EnumMember
CarFeatures cf5 = CarFeatures.DeluxePackage;
//Throws a SerializationException since neither DeluxePackage nor AlloyWheels are EnumMembers
CarFeatures cf6 = CarFeatures.None;
//Serialized as the empty list <cf6></cf6> since there is no EnumMember mapped to zero
Siehe auch
Verweis
Konzepte
Verwenden von Datenverträgen
Angeben von Datenübertragung in Dienstverträgen