Megosztás a következőn keresztül:


Számbavételi típusok az adatszerződésekben

Az enumerálások az adatszerződési modellben fejezhetők ki. Ez a témakör számos példát mutat be, amelyek a programozási modellt ismertetik.

A számbavétel alapjai

Az adatszerződés-modellben az enumerálási típusok egyik módja az DataContractAttribute attribútum alkalmazása a típusra. Ezután minden olyan tagra alkalmaznia kell az EnumMemberAttribute attribútumot, amelynek szerepelnie kell az adatszerződésben.

Az alábbi példa két osztályt mutat be. Az első az enumerálást használja, a második pedig az enumerálást.

[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

Az osztály egy példánya Car csak akkor küldhető el vagy fogadható, ha a condition mező az egyik értékre Newvan állítva , Usedvagy Rental. Ha az condition vagy BrokenStolen, SerializationException a van dobva.

A tulajdonságokat (Nameés Namespace) a DataContractAttribute szokásos módon használhatja az enumerálási adatszerződésekhez.

Tagértékek számbavétele

Az adatszerződés általában enumerálási tagneveket tartalmaz, nem numerikus értékeket. Az adatszerződés-modell használatakor azonban, ha a fogadó oldal WCF-ügyfél, az exportált séma megőrzi a numerikus értékeket. Vegye figyelembe, hogy az XmlSerializer osztály használata esetén ez nem így van.

Az előző példában, ha condition be van állítva Used , és az adatok XML-be szerializálva lesznek, az eredményként kapott XML nem <condition>Used</condition><condition>1</condition>. Ezért a következő adatszerződés egyenértékű a következő adatszerződésével 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

Használhatja például CarConditionEnum a küldő és CarConditionWithNumbers a fogadó oldalon is. Bár a küldő oldal az "1" Used értéket használja, és a fogadó oldal a "20" értéket használja, az XML-ábrázolás <condition>Used</condition> mindkét oldalra igaz.

Az adatszerződésbe való belefoglaláshoz alkalmaznia kell az EnumMemberAttribute attribútumot. A .NET-keretrendszer mindig alkalmazhatja a 0 (nulla) speciális értéket egy enumerálásra, amely szintén minden enumerálás alapértelmezett értéke. Ez a speciális nulla érték azonban csak akkor szerializálható, ha az EnumMemberAttribute attribútummal van megjelölve.

Ez alól két kivétel van:

  • Jelző számbavételek (erről a témakör későbbi részében lesz szó).

  • Az adattagok számbavétele a EmitDefaultValue következő tulajdonsággal false (ebben az esetben a nullával rendelkező enumerálás ki van hagyva a szerializált adatokból).

Enumerálási tagértékek testreszabása

Az attribútum tulajdonságával testre szabhatja az adatszerződés Value részét képező enumerálási tagértéket EnumMemberAttribute .

A következő adatszerződés például egyenértékű a következő adatszerződés adatszerződésével CarConditionEnumis.

[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

Szerializálva az érték PreviouslyOwned xml-reprezentációval <condition>Used</condition>rendelkezik.

Egyszerű számbavételek

Szerializálhatja azokat az enumerálási típusokat is, amelyekre az DataContractAttribute attribútum nem lett alkalmazva. Az ilyen enumerálási típusok kezelése pontosan a korábban leírtak szerint történik, azzal a kivételrel, hogy a rendszer minden tagot (amely nem alkalmazza az NonSerializedAttribute attribútumot) úgy kezeli a rendszer, mintha az EnumMemberAttribute attribútumot alkalmazták volna. Az alábbi enumerálás például implicit módon az előző példának megfelelő adatszerződéssel rendelkezik CarConditionEnum .

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

Egyszerű számbavételeket akkor használhat, ha nem kell testre szabnia az enumerálás adatszerződésének nevét és névterét, valamint az enumerálási tagok értékeit.

Megjegyzések az egyszerű számbavételekhez

EnumMemberAttribute Az attribútum egyszerű számbavételekre való alkalmazása nincs hatással.

Nem számít, hogy az SerializableAttribute attribútum az enumerálásra van-e alkalmazva.

Az a tény, hogy az DataContractSerializer osztály tiszteletben tartja az NonSerializedAttribute enumerálási tagokra alkalmazott attribútumot, eltér az BinaryFormatter és a SoapFormatter. Mindkét szerializáló figyelmen kívül hagyja az NonSerializedAttribute attribútumot.

Enumerációk megjelölése

Az attribútumot enumerálásokra FlagsAttribute is alkalmazhatja. Ebben az esetben a nulla vagy több számbavételi értékből álló lista egyszerre küldhető vagy fogadható.

Ehhez alkalmazza az attribútumot a DataContractAttribute jelző számbavételére, majd jelölje meg az összes olyan tagot, amely két főből áll az EnumMemberAttribute attribútummal. Vegye figyelembe, hogy a jelző számbavételének használatához a progressziónak 2-ből (például 1, 2, 4, 8, 16, 32, 64) álló erősorozatnak kell lennie.

A jelölő enumerálási értékének elküldésére az alábbi lépések vonatkoznak:

  1. Próbáljon meg olyan számbavételi tagot keresni (az EnumMemberAttribute attribútummal együtt), amely megfelel a numerikus értéknek. Ha megtalálta, küldjön egy listát, amely csak az adott tagot tartalmazza.

  2. Próbálja meg a numerikus értéket olyan összegre bontani, hogy az összeg egyes részeihez tartozó enumerálási tagok (mindegyik az alkalmazott attribútummal EnumMemberAttribute ) legyenek leképezve. Küldje el az összes tag listáját. Vegye figyelembe, hogy a kapzsi algoritmust használják egy ilyen összeg megkeresésére, és így nincs garancia arra, hogy az ilyen összeg akkor is megtalálható, ha jelen van. A probléma elkerülése érdekében győződjön meg arról, hogy az enumerálási tagok numerikus értékei két hatványból állnak.

  3. Ha az előző két lépés sikertelen, és a numerikus érték nem nulla, dobjon egy SerializationException. Ha a numerikus érték nulla, küldje el az üres listát.

Példa

A következő felsorolási példa használható egy jelölőműveletben.

[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

A következő példaértékek a jelzett módon szerializálva vannak.

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.

Lásd még