如何在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 CategorySpecified
为true
,否则不会序列化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; }