XmlSerialize поле Enum Flag - PullRequest
       51

XmlSerialize поле Enum Flag

11 голосов
/ 23 января 2012

У меня есть это:

    [Flags]
    public enum InfoAbonne{civilite,name,firstname,email,adress,country }

    public class Formulaire
    {
      private InfoAbonne _infoAbonne{ get; set;}
      public Formulaire()
      {}
    }

Я хочу сериализовать Xml Formulaire

Если я инициирую:
_infoAbonne = InfoAbonne.name | InfoAbonne.email;

В моем XML-результате я получаютолько:

<InfoAbonne>email</InfoAbonne>

Ответы [ 4 ]

15 голосов
/ 23 января 2012

Даже если вы добавили атрибут Flags к своему перечислению, вам все равно нужно убедиться, что значения имеют степени двойки:

[Flags]
public enum InfoAbonne
{
    civilite = 1,
    name = 2,
    firstname = 4,
    email = 8,
    adress = 16,
    country = 32
}

См. Рекомендации, изложенные в Замечаниях раздел документации .

8 голосов
/ 23 января 2012

Основная идея с такими проблемами - сериализация вспомогательного поля, которое имитирует поле, которое вы хотите сериализовать. Тот же принцип может быть применен к сложным типам, таким как растровые изображения и т. Д. Например, вместо прямой сериализации поля Enum, вы можете сериализовать вспомогательное поле типа int:

// Disclaimer: Untested code, both in execution and compilation
[Flags]      
public enum InfoAbonne 
{
    civilite = 0x1, // Increment each flag value by *2 so they dont conflict
    Name=0x2,
    firstname=0x4,
    email=0x8,
    adress=0x10,
    country=0x20 
}  

// Don't serialize this field
[XmlIgnore]
private InfoAbonne _infoAbonne { get; set;} 

// Instead serialize this field as integer
// e.g. name | email will equal 0xA in hex, or 10 in dec
[XmlElement("InfoAbonne")]
private InfoAbonneSerializer 
{ 
    get { return (int)_infoAbonne; } 
    set { _infoAbonne= (InfoAbonne) value; } 
} 

С уважением,

0 голосов
/ 01 марта 2017
[Flags]
public enum InfoAbonne
{
    civilite = (1 << 0),
    name = (1 << 1),
    firstname = (1 << 2),
    email = (1 << 3),
    adress = (1 << 4),
    country = (1 << 5)
}
0 голосов
/ 15 октября 2014

Dr.Ответ АБТ лучше, чем выбранный ответ.Да, иметь значения в степени 2 необходимо, но это не относится к проблемам сериализации XML.

Перечисления сериализуются совсем иначе, чем большинство объектов.Перечисления будут XML-сериализованными по их имени (ser(MyEnumProperty.[Name]) = "[Name]") вместо использования имени (ser(MyEnumProperty.[Name]) = 8).

// Version 1.0
[Flags]      
public enum MyEnum
{
    None = 0,
    First = 1,
    Second = 2,
    All = First | Second
}

public MyEnum MyEnumProperty = MyEnum.All;

Если бы вы сериализовали MyEnumProperty, вы бы получили <MyEnum>All</MyEnum>.Однако, если вы сериализовали (int)MyEnumProperty, вы получите <int>3</int>.Я хотел бы упомянуть, почему это невероятно необходимо знать ...

// Version 2.0
[Flags]      
public enum MyEnum
{
    None = 0,
    First = 1,
    Second = 2,
    Third = 4, // <---
    All = First | Second | Third
}

Я добавил новые значения Enum, которые могли бы использоваться (как DLL) в других проектах.Ух ты ... что это за ошибки?

Вы больше не можете десериализовать вашу новейшую версию enum в более старую версию с XML-сериализацией ( Binary Serialization все еще должна работать)!

Взгляните на метод ToEnum от Microsoft.Это предотвращает просмотр идентификатора (скажем, «Третий» в обновленном перечислении), поскольку он не существует в исходном перечислении.Также обратите внимание, что будет выдано сообщение об ошибке, которое может нарушить ваш проект, если он не будет обработан.

Будьте осторожны, всегда сериализуйте и десериализуйте по значению, когда есть такая возможность.Вот почему для начала мы используем такие объекты, как помеченные перечисления.Такие объекты, как помеченные перечисления, уменьшают проблемы обратной совместимости и зависимости.

...