Несогласованное поведение атрибута DataContractAttribute
-
19-09-2019 - |
Вопрос
насколько я понимаю, модель контракта на передачу данных WCF была основана на отказе от старого подхода веб-служб asmx.вы должны явно указать все поля и типы, которые вам требуется использовать DataContractAttribute
и DataMemberAttribute
.однако мой опыт был иным.
взгляните на следующие примеры,
///CASE: 1
///Behaves as excpected BoolValue is included but String Value is emitted
[DataContract]
public class CompositeType
{
[DataMember]
public bool BoolValue { get; set; }
public string StringValue { get; set; }
}
///CASE: 2
///All elements are included, as if everything was marked.
public class CompositeType
{
public bool BoolValue { get; set; }
public string StringValue { get; set; }
}
///CASE: 3
/// MyEnum Type is included even though the MyEnum is not marked.
[DataContract]
public class CompositeType
{
[DataMember]
public bool BoolValue { get; set; }
[DataMember]
public string StringValue { get; set; }
[DataMember]
public MyEnum EnumValue{ get; set; }
}
public enum MyEnum
{
hello = 0,
bye = 1
}
///CASE: 4
/// MyEnum Type is no longer included. EnumValue is serialized as a string
[DataContract]
public class CompositeType
{
[DataMember]
public bool BoolValue { get; set; }
[DataMember]
public string StringValue { get; set; }
[DataMember]
public MyEnum EnumValue{ get; set; }
}
[DataContract]
public enum MyEnum
{
hello = 0,
bye = 1
}
///CASE: 5
//Both hello and bye are serilized
public enum MyEnum
{
[EnumMember]
hello = 0,
bye = 1
}
///CASE: 6
//only hello is serilized
[DataContract]
public enum MyEnum
{
[EnumMember]
hello = 0,
bye = 1
}
Все, что я могу сказать, это WCF WTF?
Решение
Перечисления всегда сериализуемы по определению.Когда вы определяете новое перечисление, нет необходимости применять к нему атрибут DataContract, и вы можете свободно использовать его в контракте данных.Если вы хотите исключить определенные значения перечисления из контракта данных, вам нужно сначала украсить перечисление атрибутом DataContract.Затем явно примените атрибут EnumMemberAttribute ко всем значениям enum, которые вы хотите включить в контракт enum data.Вот так
[DataContract]
enum ContactType
{
[EnumMember]
Customer,
[EnumMember]
Vendor,
//Will not be part of data contract
Partner
}
приведет к этому проводному представлению:
enum ContactType
{
Customer,
Vendor
}
Что неверно для классов, что объясняет первый случай, см. Программирование сервисов WCF
Другие советы
Примечание:Я не работал с WCF, и это основано исключительно на чтении.
Случай 2:Если CompositeType используется в качестве свойства / поля / возвращаемого значения сервиса, оно будет сериализовано (поскольку является общедоступным).
Случай 3:То же, что и в случае 2.Поскольку тип контейнера является сериализуемым, перечисление (хотя оно и не помечено) будет сериализовано.
Случай 4:Перечисление будет сериализовано как строка.Вы можете использовать свойство Value при применении EnumMember для изменения сериализованного значения.
Случай 5:То же, что и в случае 2
Случай 6:Вы явно используете Enum и применили DataContract, DataMember для одного из значений enum.Тем самым указывая сериализатору игнорировать другой элемент перечисления.
Пожалуйста, не будьте критичны, так как это основано исключительно на беглом взгляде на чтение документа :)