数据协定中的枚举类型

枚举基础知识

若要使用以数据协定模型表示的枚举类型,一种方法就是将 DataContractAttribute 属性应用于该类型。然后,必须将 EnumMemberAttribute 属性应用于每个必须在数据协定中包含的成员。

下面的示例演示了两个类。第一个类使用枚举,第二个类定义枚举。

    [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
    }
仅当将 condition 字段的值设置为 NewUsedRental 之一时,才可发送或接收 Car 类的实例。如果 conditionBrokenStolen,则会引发一个 SerializationException

可以照常将 DataContractAttribute 属性(NameNamespace)用于枚举数据协定。

枚举成员值

通常数据协定包括枚举成员名称,而不包括数值。但是,如果使用数据协定模型并且接收端为 WCF 客户端,则导出的架构保留数值。请注意,如果使用 使用 XmlSerializer 类,则情况并非如此。

在上面的示例中,如果将 condition 设置为 Used 并且将数据序列化为 XML,则生成的 XML 是 <condition>Used</condition> 而不是 <condition>1</condition>。因此,下面的数据协定等效于 CarConditionEnum 的数据协定。

    [DataContract(Name  =   " CarCondition " )]
    
public   enum  CarConditionWithNumbers
    {
        [EnumMember]
        New 
=   10 ,
        [EnumMember]
        Used 
=   20 ,
        [EnumMember]
        Rental 
=   30 ,
    }

 

例如,您可以在发送端使用 CarConditionEnum 并且在接收端使用 CarConditionWithNumbers。尽管发送端的 Used 使用值“1”而接收端使用值“20”,但是两端的 XML 表示形式均为 <condition>Used</condition>

若要包含在数据协定中,必须应用 EnumMemberAttribute 属性。在 .NET Framework 中,可以始终将特殊值 0(零)应用到枚举中,它是任何枚举的默认值。但是,即使对于此特殊值零,也只能使用 EnumMemberAttribute 属性标记才能进行序列化。

以下为此规则的两种例外情况:

  • 标志枚举。

  • EmitDefaultValue 属性设置为 false 的枚举数据成员(这种情况下将从序列化数据中省略值为零的枚举)。

自定义枚举成员值

可以通过使用 EnumMemberAttribute 属性 (attribute) 的 Value 属性 (property) 对作为数据协定构成部分的枚举成员值进行自定义。

例如,下面的数据协定也等效于 CarConditionEnum 的数据协定。

    [DataContract(Name  =   " CarCondition " )]
    
public   enum  CarConditionWithDifferentNames
    {
        [EnumMember(Value 
=   " New " )]
        BrandNew,
        [EnumMember(Value 
=   " Used " )]
        PreviouslyOwned,
        [EnumMember]
        Rental
    }

在序列化时,PreviouslyOwned 的值的 XML 表示形式为 <condition>Used</condition>

简单枚举

您还可以对未向其应用 DataContractAttribute 属性的枚举类型进行序列化。可以按照上述方式来处理这种枚举类型,只不过将每个成员(这些成员未应用 NonSerializedAttribute 属性)视为已应用了 EnumMemberAttribute 属性。例如,下面的枚举隐式具有一个与上面的 CarConditionEnum 示例等效的数据协定。

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

 

如果您不需要自定义枚举的数据协定名称、命名空间以及枚举成员值,则可以使用简单枚举。

简单枚举说明

EnumMemberAttribute 属性应用于简单枚举是无效的。

是否将 SerializableAttribute 属性应用于简单枚举并没有任何区别。

DataContractSerializer 类采用应用于枚举成员的 NonSerializedAttribute 属性的事实不同于 BinaryFormatterSoapFormatter 的行为。这两种序列化程序都忽略 NonSerializedAttribute 属性。

标志枚举

可以将 FlagsAttribute 属性应用于枚举。在这种情况下,可以同时发送或接收包含零个或多个枚举值的列表。

为此,请将 DataContractAttribute 属性应用于标志枚举,然后使用 EnumMemberAttribute 属性对所有为 2 的幂的成员进行标记。请注意,若要使用标志枚举,级数必须为不间断的 2 的幂的序列(例如,1、2、4、8、16、32、64)。

可以使用下面的步骤来发送标志的枚举值:

  1. 尝试查找映射到数值的枚举成员(应用了 EnumMemberAttribute 属性)。如果可以找到,请发送仅包含该成员的列表。

  2. 尝试将此数值分解为和的形式,以便枚举成员(每个成员都应用了 EnumMemberAttribute 属性)可以映射到和的各个部分。发送包含所有这些成员的列表。请注意,将使用“贪婪算法”查找这样的和,因此即使存在这样的和,也不一定能找到它。为避免出现这种问题,请确保枚举成员的数值为 2 的幂。

  3. 如果上面的两个步骤均无法实现并且数值为非零,则引发一个 SerializationException。如果数值为零,则发送空列表。

示例

下面的枚举示例可用于标志操作。

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
}

 

下面的示例值将按照指示的方式进行序列化。


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

转载于:https://www.cnblogs.com/jeriffe/articles/2084254.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值