Код сервера
<DataContract(Namespace:="http://schema.aam.us.com/2010/6", Name:="TradeStatus")>
Public Enum TradeStatus
NewOrder = 100
SendToProvider = 101
ProviderSubmitted = 102
ProviderAccepted = 103
ExecutionPending = 104
Executed = 105
TicketsCreated = 106 'TERMINAL STATE
End Enum
<DataContract(Namespace:="http://schema.aam.us.com/2010/6", Name:="StatusUpdate")> _
Public Class StatusUpdate
Public Sub New(ByVal tradeStatus As TradeStatus, ByVal additionalInformation As String)
Me.TradeStatus = tradeStatus
Me.AdditionalInforamtion = additionalInformation
End Sub
<DataMember(IsRequired:=True)> _
Public Property AdditionalInforamtion() As String
<DataMember(IsRequired:=True)> _
Public Property TradeStatus() As TradeStatus
End Class
Сгенерированный код
<System.Diagnostics.DebuggerStepThroughAttribute(), _
System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0"), _
System.Runtime.Serialization.DataContractAttribute(Name:="StatusUpdate", [Namespace]:="http://schema.aam.us.com/2010/6"), _
System.SerializableAttribute()> _
Partial Public Class StatusUpdate
Inherits Object
Implements System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged
<System.NonSerializedAttribute()> _
Private extensionDataField As System.Runtime.Serialization.ExtensionDataObject
Private AdditionalInforamtionField As String
Private TradeStatusField As String
<Global.System.ComponentModel.BrowsableAttribute(false)> _
Public Property ExtensionData() As System.Runtime.Serialization.ExtensionDataObject Implements System.Runtime.Serialization.IExtensibleDataObject.ExtensionData
Get
Return Me.extensionDataField
End Get
Set
Me.extensionDataField = value
End Set
End Property
<System.Runtime.Serialization.DataMemberAttribute(IsRequired:=true)> _
Public Property AdditionalInforamtion() As String
Get
Return Me.AdditionalInforamtionField
End Get
Set
If (Object.ReferenceEquals(Me.AdditionalInforamtionField, value) <> true) Then
Me.AdditionalInforamtionField = value
Me.RaisePropertyChanged("AdditionalInforamtion")
End If
End Set
End Property
<System.Runtime.Serialization.DataMemberAttribute(IsRequired:=true, EmitDefaultValue:=false)> _
Public Property TradeStatus() As String
Get
Return Me.TradeStatusField
End Get
Set
If (Object.ReferenceEquals(Me.TradeStatusField, value) <> true) Then
Me.TradeStatusField = value
Me.RaisePropertyChanged("TradeStatus")
End If
End Set
End Property
Public Event PropertyChanged As System.ComponentModel.PropertyChangedEventHandler Implements System.ComponentModel.INotifyPropertyChanged.PropertyChanged
Protected Sub RaisePropertyChanged(ByVal propertyName As String)
Dim propertyChanged As System.ComponentModel.PropertyChangedEventHandler = Me.PropertyChangedEvent
If (Not (propertyChanged) Is Nothing) Then
propertyChanged(Me, New System.ComponentModel.PropertyChangedEventArgs(propertyName))
End If
End Sub
End Class
Перечисления сериализуются по умолчанию. Как и в классах primites и Collection, вам не нужно помечать их [DataContract]. Однако это не означает, что WCF не позволяет настраивать поведение сериализации, поэтому в духе взаимодействия можно изменить способ сериализации enum. В рамках этой настраиваемости, если вы помечаете его с помощью DataContract, но не помечаете EnumMembers, вы изменяете схему сериализации по умолчанию. Подробнее о сериализации Enum читайте здесь Enum Serialization
EDIT:Я подумал немного больше об этом, и теперь я начал задаваться вопросом о основной причине... оказывается, это вина WSDL.
По умолчанию, если вы не ставите [DataContract], WCF по умолчанию сериализует enum, как если бы у него был атрибут [DataContract] и [EnumMembers]. Итак, если вы возьмете следующий пример
[DataContract]
public enum FileType {
[EnumMember]
Text,
[EnumMember]
Pdf,
[EnumMember]
Word
}
, он сгенерирует следующий WSDL
<xs:simpleType name="FileType">
<xs:restriction base="xs:string">
<xs:enumeration value="Text" />
<xs:enumeration value="Pdf" />
<xs:enumeration value="Word" />
</xs:restriction>
</xs:simpleType>
<xs:element name="FileType" nillable="true" type="tns:FileType" />
Итак, теперь, если вы уберете атрибуты [EnumMember], подобные so
[DataContract]
public enum FileType {
Text,
Pdf,
Word
}
, ваш WSDL будет выглядеть следующим образом:
<xs:simpleType name="FileType">
<xs:restriction base="xs:string" />
</xs:simpleType>
<xs:element name="FileType" nillable="true" type="tns:FileType" />
Таким образом, второй выглядит так же, как первый, за исключением без элементов перечисления. В чем же разница между вторым и просто WSDL, описывающим простую строку? Никакой. Вот почему поколение прокси-сервера WCF дает строку вместо Enum.
Если вы включаете атрибут DataContract
, вам необходимо пометить по крайней мере одно значение атрибутом EnumMember
. В противном случае он не сможет увидеть ни одно из значений и превратит все поле в строку.
Если вы не включаете атрибут DataContract
, вам также не нужен атрибут EnumMember
.
РЕДАКТИРОВАТЬ: Пример правильного кода
<DataContract(Namespace:="http://schema.aam.us.com/2010/6", Name:="TradeStatus")>
Public Enum TradeStatus
<EnumMember> NewOrder = 100
<EnumMember> SendToProvider = 101
<EnumMember> ProviderSubmitted = 102
<EnumMember> ProviderAccepted = 103
<EnumMember> ExecutionPending = 104
<EnumMember> Executed = 105
<EnumMember> TicketsCreated = 106 'TERMINAL STATE
End Enum
Простота - вот как это должно работать.
В XML Schema нет понятия перечисления, в смысле пары имя/значение. Самое близкое к этому - возможность указать, что определенный простой тип может иметь одно из нескольких значений - в данном случае строковые значения.
Обратите внимание, что веб-сервисы ASMX и XML Serializer делают точно то же самое.
Хорошо, мы с Джонатаном оба правы и оба неправы.
При сериализации перечисления WCF добавляет специфическую для .NET информацию к XML-схеме. Это позволяет другой реализации .NET рассматривать перечисление как перечисление, в комплекте с сохранением значений перечисления.
Однако никакая другая платформа не сможет понять эту информацию. В результате перечисление будет рассматриваться просто как строка, которая может принимать только одно из нескольких значений.