如何在C#中序列化/反序列化可选的XML枚举?

我试图弄清楚如何将XML列表序列化/反序列化为C#,它具有枚举类型的可选属性。 以下是我的C#类:

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

我的Category枚举定义如下:

 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 } 

Category出现在相应的XML文件中时,序列化/反序列化按预期工作。 但是,如果XML中缺少Category ,则使用默认值(枚举中的第一项)。 如果我尝试使枚举变量可以为空( Category? ),则反序列化器会抛出exception,因为它无法反序列化复杂类型。 给定以下XML(不包含该属性),如何正确地序列化枚举?

   

在这种情况下,反序列化对象中的值应为null。

谢谢你尽你所能的帮助!

好吧,你可以这样做 – 但它有点乱:

 [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; } 

这是做什么的:

  • 使用Category? 对于可选的枚举值
  • 禁用Category属性以进行序列化
  • 添加一个辅助属性, CategorySerialized ,作为CategorySerialized的代理,从IDE等不可空和隐藏(尽可能)
  • 通过ShouldSerialize*模式在CategorySerialized上使用条件序列化

实际上,有一些官方魔术允许这样做( 见这里 ):

另一种选择是使用特殊模式来创建XmlSerializer可识别的布尔字段,并将XmlIgnoreAttribute应用于该字段。 该模式以propertyNameSpecified的forms创建。 例如,如果有一个名为“MyFirstName”的字段,您还将创建一个名为“MyFirstNameSpecified”的字段,该字段指示XmlSerializer是否生成名为“MyFirstName”的XML元素。 这在以下示例中显示。

也就是说,TS案例中的模型应如下所示:

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

除非将magic CategorySpecifiedtrue ,否则不会序列化Category属性。 在反序列化的情况下, CategorySpecified将为false ,表示XML中不存在Category

使用“指定”模式的完整示例代码

 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; }