Delen via


Opsommingstypen in gegevenscontracten

Opsommingen kunnen worden uitgedrukt in het gegevenscontractmodel. In dit onderwerp worden verschillende voorbeelden beschreven die het programmeermodel uitleggen.

Basisbeginselen van opsomming

Een manier om opsommingstypen in het gegevenscontractmodel te gebruiken, is door het DataContractAttribute kenmerk toe te passen op het type. Vervolgens moet u het EnumMemberAttribute kenmerk toepassen op elk lid dat moet worden opgenomen in het gegevenscontract.

In het volgende voorbeeld ziet u twee klassen. De eerste maakt gebruik van de opsomming en de tweede definieert de opsomming.

[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
}
<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

Een exemplaar van de Car klasse kan alleen worden verzonden of ontvangen als het condition veld is ingesteld op een van de waarden New, Usedof Rental. Als het condition is Broken of Stolen, wordt er een SerializationException gegooid.

U kunt de DataContractAttribute eigenschappen (Name en Namespace) zoals gebruikelijk gebruiken voor opsommingsgegevenscontracten.

Waarden van opsommingslid

Over het algemeen bevat het gegevenscontract namen van opsommingsleden, niet numerieke waarden. Wanneer u echter het gegevenscontractmodel gebruikt en de ontvangende zijde een WCF-client is, behoudt het geƫxporteerde schema de numerieke waarden. Houd er rekening mee dat dit niet het geval is wanneer u de klasse XmlSerializer gebruikt.

Als in het voorgaande voorbeeld condition is ingesteld op Used en de gegevens worden geserialiseerd op XML, is <condition>Used</condition> de resulterende XML en niet <condition>1</condition>. Daarom is het volgende gegevenscontract gelijk aan het gegevenscontract van CarConditionEnum.

[DataContract(Name = "CarCondition")]
public enum CarConditionWithNumbers
{
    [EnumMember]
    New = 10,
    [EnumMember]
    Used = 20,
    [EnumMember]
    Rental = 30,
}
<DataContract(Name:="CarCondition")> _
Public Enum CarConditionWithNumbers
    <EnumMember> NewCar = 10
    <EnumMember> Used = 20
    <EnumMember> Rental = 30
End Enum

U kunt bijvoorbeeld aan de verzendzijde en CarConditionWithNumbers aan de ontvangstzijde gebruikenCarConditionEnum. Hoewel de verzendende zijde de waarde '1' gebruikt en Used de ontvangende zijde de waarde '20' gebruikt, is <condition>Used</condition> de XML-weergave voor beide zijden.

Als u wilt worden opgenomen in het gegevenscontract, moet u het EnumMemberAttribute kenmerk toepassen. In .NET Framework kunt u altijd de speciale waarde 0 (nul) toepassen op een opsomming. Dit is ook de standaardwaarde voor elke opsomming. Zelfs deze speciale nulwaarde kan echter niet worden geserialiseerd, tenzij deze is gemarkeerd met het EnumMemberAttribute kenmerk.

Er zijn twee uitzonderingen hierop:

  • Markeringen markeren (verderop in dit onderwerp besproken).

  • Opsommingsgegevensleden waarop de EmitDefaultValue eigenschap is ingesteld false (in dat geval wordt de opsomming met de waarde nul weggelaten uit de geserialiseerde gegevens).

Waarden van opsommingsleden aanpassen

U kunt de waarde van het opsommingslid aanpassen die deel uitmaakt van het gegevenscontract met behulp van de Value eigenschap van het EnumMemberAttribute kenmerk.

Het volgende gegevenscontract is bijvoorbeeld ook gelijk aan het gegevenscontract van het CarConditionEnum.

[DataContract(Name = "CarCondition")]
public enum CarConditionWithDifferentNames
{
    [EnumMember(Value = "New")]
    BrandNew,
    [EnumMember(Value = "Used")]
    PreviouslyOwned,
    [EnumMember]
    Rental
}
<DataContract(Name:="CarCondition")> _
Public Enum CarConditionWithDifferentNames
    <EnumMember(Value:="New")> BrandNew
    <EnumMember(Value:="Used")> PreviouslyOwned
    <EnumMember> Rental
End Enum

Wanneer deze wordt geserialiseerd, heeft de waarde PreviouslyOwned de XML-weergave <condition>Used</condition>.

Eenvoudige opsommingen

U kunt ook opsommingstypen serialiseren waarop het DataContractAttribute kenmerk niet is toegepast. Dergelijke opsommingstypen worden precies zoals eerder beschreven behandeld, behalve dat elk lid (dat niet het NonSerializedAttribute kenmerk heeft toegepast) wordt behandeld alsof het EnumMemberAttribute kenmerk is toegepast. De volgende opsomming heeft bijvoorbeeld impliciet een gegevenscontract dat gelijk is aan het voorgaande CarConditionEnum voorbeeld.

public enum CarCondition
{
    New,
    Used,
    Rental,
    [NonSerialized]
    Lost
}
Public Enum CarCondition
    [New]
    Used
    Rental
End Enum

U kunt eenvoudige opsommingen gebruiken wanneer u de naam en naamruimte van het gegevenscontract van de opsomming niet hoeft aan te passen en de waarden van de opsommingslid.

Notities over eenvoudige opsommingen

Het toepassen van het EnumMemberAttribute kenmerk op eenvoudige opsommingen heeft geen effect.

Het maakt geen verschil of het SerializableAttribute kenmerk al dan niet wordt toegepast op de opsomming.

Het feit dat de DataContractSerializer klasse het NonSerializedAttribute kenmerk respecteert dat wordt toegepast op opsommingsleden, verschilt van het gedrag van de BinaryFormatter en de SoapFormatter. Beide serializers negeren het NonSerializedAttribute kenmerk.

Opsommingen markeren

U kunt het FlagsAttribute kenmerk toepassen op opsommingen. In dat geval kan een lijst met nul of meer opsommingswaarden tegelijk worden verzonden of ontvangen.

Als u dit wilt doen, past u het DataContractAttribute kenmerk toe op de vlag-opsomming en markeert u vervolgens alle leden die bevoegdheden van twee met het EnumMemberAttribute kenmerk hebben. Houd er rekening mee dat als u een vlag-opsomming wilt gebruiken, de voortgang een ononderbroken reeks machten van 2 moet zijn (bijvoorbeeld 1, 2, 4, 8, 16, 32, 64).

De volgende stappen zijn van toepassing op het verzenden van de opsommingswaarde van een vlag:

  1. Probeer een opsommingslid te vinden (waarbij het EnumMemberAttribute kenmerk is toegepast) dat is toegewezen aan de numerieke waarde. Indien gevonden, verzendt u een lijst die alleen dat lid bevat.

  2. Probeer de numerieke waarde op te splitsen in een som, zodat er opsommingsleden zijn (elk met het EnumMemberAttribute kenmerk dat is toegepast) die aan elk deel van de som zijn toegewezen. Verzend de lijst met al deze leden. Houd er rekening mee dat het greedy-algoritme wordt gebruikt om een dergelijke som te vinden, en er is dus geen garantie dat een dergelijke som wordt gevonden, zelfs als deze aanwezig is. Om dit probleem te voorkomen, moet u ervoor zorgen dat de numerieke waarden van de opsommingsleden de bevoegdheden van twee zijn.

  3. Als de voorgaande twee stappen mislukken en de numerieke waarde niet nul is, genereert u een SerializationException. Als de numerieke waarde nul is, verzendt u de lege lijst.

Opmerking

Het volgende opsommingsvoorbeeld kan worden gebruikt in een vlagbewerking.

[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
}
<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

De volgende voorbeeldwaarden worden geserialiseerd zoals aangegeven.

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
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.

Zie ook