Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Výčty lze vyjádřit v modelu kontraktu dat. Toto téma vás provede několika příklady, které vysvětlují programovací model.
Základy výčtu
Jedním ze způsobů, jak použít typy výčtu v modelu kontraktu dat, je použít DataContractAttribute atribut na typ. Pak musíte atribut použít EnumMemberAttribute pro každého člena, který musí být zahrnut do datové smlouvy.
Následující příklad ukazuje dvě třídy. První používá výčet a druhý definuje výčet.
[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
Instanci Car třídy lze odeslat nebo přijímat pouze v případě, že condition je pole nastaveno na jednu z hodnot New, Usednebo Rental.
condition Pokud je Broken nebo Stolen, SerializationException je vyvolán.
Vlastnosti DataContractAttribute (Name a Namespace) můžete použít jako obvykle pro výčtové kontrakty dat.
Hodnoty členů výčtu
Obecně platí, že kontrakt dat obsahuje názvy členů výčtu, nikoli číselné hodnoty. Pokud je však přijímající strana klientem WCF, při použití modelu kontraktu dat zachová exportované schéma číselné hodnoty. Všimněte si, že to není případ při použití třídy XmlSerializer.
V předchozím příkladu pokud je condition nastaveno na Used a data jsou serializována do XML, výsledné XML je <condition>Used</condition> a nikoli <condition>1</condition>. Z tohoto důvodu je následující datový kontrakt ekvivalentní datové smlouvě .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
Můžete například použít CarConditionEnum na straně odesílání a CarConditionWithNumbers na straně příjmu. I když odesílající strana používá hodnotu "1" pro Used a přijímající strana používá hodnotu "20", reprezentace XML je <condition>Used</condition> pro obě strany.
Pokud chcete být zahrnuti do datového kontraktu EnumMemberAttribute , musíte použít atribut. V rozhraní .NET Framework můžete vždy použít speciální hodnotu 0 (nula) na výčet, což je také výchozí hodnota pro všechny výčty. I tuto speciální nulovou hodnotu však nelze serializovat, pokud není označen atributem EnumMemberAttribute .
Existují dvě výjimky:
Výčty vlajkových příznaků (popsané dále v tomto tématu).
Datové členy výčtu s vlastností nastavenou EmitDefaultValue na
false(v takovém případě je výčet s hodnotou nula vynechán ze serializovaných dat).
Přizpůsobení hodnot členů výčtu
Hodnotu člena výčtu, která tvoří součást datového kontraktu, můžete přizpůsobit pomocí Value vlastnosti atributu EnumMemberAttribute .
Například následující datový kontrakt je také ekvivalentní datovému kontraktu 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
Při serializaci má hodnota PreviouslyOwned XML reprezentaci <condition>Used</condition>.
Jednoduché výčty
Můžete také serializovat typy výčtu, na které DataContractAttribute atribut nebyl použit. Takové typy výčtu jsou zacházeno přesně tak, jak bylo popsáno dříve, s tím rozdílem, že každý člen, na který není aplikován atribut NonSerializedAttribute, je považován, jako by byl atribut EnumMemberAttribute použit. Například následující výčet implicitně obsahuje kontrakt dat ekvivalentní předchozímu CarConditionEnum příkladu.
public enum CarCondition
{
New,
Used,
Rental,
[NonSerialized]
Lost
}
Public Enum CarCondition
[New]
Used
Rental
End Enum
Jednoduché výčty můžete použít v případě, že nepotřebujete přizpůsobit název datového kontraktu, obor názvů a hodnoty členů výčtu.
Poznámky k jednoduchým výčtům
Použití atributu EnumMemberAttribute na jednoduché výčty nemá žádný vliv.
Nezáleží na tom, zda SerializableAttribute je atribut použit na výčet.
Skutečnost, že DataContractSerializer třída respektuje NonSerializedAttribute atribut použitý na výčtové členy se liší od chování BinaryFormatter a SoapFormatter. Oba tyto serializátory ignorují atribut NonSerializedAttribute.
Výčty příznaků
Atribut můžete použít FlagsAttribute na výčty. V takovém případě může být současně odeslán nebo přijat seznam nulových nebo více hodnot výčtu.
Abyste to provedli, aplikujte na výčet příznaku atribut DataContractAttribute a poté označte všechny členy, které jsou mocninami dvou, atributem EnumMemberAttribute. Všimněte si, že pokud chcete použít výčet příznaků, musí být průběh nepřerušenou posloupností mocnin 2 (například 1, 2, 4, 8, 16, 32, 64).
Následující kroky platí pro odeslání hodnoty výčtu příznaku:
Pokusit se o nalezení členu výčtu (s použitým atributem EnumMemberAttribute), který se mapuje na číselnou hodnotu. Pokud se najde, odešlete seznam, který obsahuje jenom daného člena.
Pokusit se rozložit číselnou hodnotu na součet tak, aby byly k dispozici prvky výčtu (každý s použitým EnumMemberAttribute atributem), které odpovídají každé části součtu. Odešlete seznam všech těchto členů. Všimněte si, že algoritmus greedy se používá k nalezení takového součtu, a proto neexistuje žádná záruka, že takový součet se najde i v případě, že existuje. Chcete-li se tomuto problému vyhnout, ujistěte se, že číselné hodnoty členů výčtu jsou mocniny dvou.
Pokud předchozí dva kroky selžou a číselná hodnota je nenulová, vyvoláte výjimku SerializationException. Pokud je číselná hodnota nula, odešlete prázdný seznam.
Příklad
Následující příklad výčtu lze použít v operaci příznaku.
[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
Následující ukázkové hodnoty jsou serializovány, jak je uvedeno.
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.