¿Cómo serializar / deserializar la enumeración XML opcional en C #?

Estoy tratando de averiguar cómo serializar / deserializar una lista XML a C # que tiene un atributo opcional que es un tipo enumerado. La siguiente es mi clase de C #:

public class AttributeAssignmentExpressionElement : XACMLElement { [XmlAttribute] public string AttributeId { get; set; } [XmlAttribute] public Category Category { get; set; } } 

La enumeración de mi Category se define de la siguiente manera:

 public enum Category { [XmlEnum(Name = "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject")] Subject, [XmlEnum(Name = "urn:oasis:names:tc:xacml:3.0:attribute-category:resource")] Resource, [XmlEnum(Name = "urn:oasis:names:tc:xacml:3.0:attribute-category:action")] Action, [XmlEnum(Name = "urn:oasis:names:tc:xacml:3.0:attribute-category:environment")] Environment } 

Cuando la Category está presente en el archivo XML correspondiente, la serialización / deserialización funciona como se esperaba. Sin embargo, si la Category falta en el XML, se usa el valor predeterminado (primer elemento en la enumeración). Si bash hacer que la variable enumerada sea anulable ( Category? ), El deserializador lanza una excepción porque no puede deserializar un tipo complejo. Dado el siguiente XML (que no contiene el atributo), ¿cómo puedo serializar la enumeración apropiadamente?

   

En esta situación, el valor en el objeto deserializado debe ser nulo.

¡Gracias por cualquier ayuda que pueda ofrecer!

Bueno, puedes hacer esto, pero es un poco desordenado:

 [XmlIgnore] public Category? Category { get; set; } [XmlAttribute("Category")] [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public Category CategorySerialized {  get { return Category.Value; }  set { Category = value; } } [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] public bool ShouldSerializeCategorySerialized() {  return Category.HasValue; } 

Lo que esto hace:

  • utiliza una Category? para el valor de enumeración opcional
  • desactiva la propiedad Category para la serialización
  • agrega una propiedad secundaria, CategorySerialized , como un proxy a la Category , que no es anulable y está oculta (en la medida de lo posible) del IDE, etc.
  • use la serialización condicional en CategorySerialized través del patrón ShouldSerialize*

En realidad, hay algo de magia oficial que permite hacer esto ( ver aquí ):

Otra opción es usar un patrón especial para crear un campo booleano reconocido por el XmlSerializer y aplicar el atributo XmlIgnoreAttribute al campo. El patrón se crea en la forma de propertyNameSpecified. Por ejemplo, si hay un campo llamado “MyFirstName”, también creará un campo llamado “MyFirstNameSpecified” que le indica al XmlSerializer si debe generar el elemento XML llamado “MyFirstName”. Esto se muestra en el siguiente ejemplo.

Es decir, el modelo en el caso de TS debería verse así:

 public class AttributeAssignmentExpressionElement : XACMLElement { [XmlAttribute] public string AttributeId { get; set; } [XmlAttribute] public Category Category { get; set; } [XmlIgnore] public bool CategorySpecified { get; set; } } 

A menos que configure el campo mágico CategorySpecified en true , el atributo Category no se serializará. En caso de deserialización, la CategorySpecified especificada será false , lo que indica que la Category no estaba presente en XML.

El código de muestra completo usando el patrón ‘Especificado’

 public class ClassToSerialize { [XmlAttribute("attributeName")] public EnumType EnumPropertyValue { get { return EnumProperty.Value; } set { EnumProperty = value; } } [XmlIgnore] public EnumType? EnumProperty { get; set; } public bool EnumPropertyValueSpecified => EnumProperty.HasValue; }