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

时间:2012-05-31 19:39:39

标签: c# xml xml-serialization

我试图弄清楚如何将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
}  

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

<AttributeAssignmentExpression
    AttributeId="urn:oasis:names:tc:xacml:3.0:example:attribute:text">       
</AttributeAssignmentExpression>

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

感谢您提供的任何帮助!

3 个答案:

答案 0 :(得分:13)

嗯,你可以这样做 - 但它有点乱:

[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添加为Category的代理,该代理不可空,并且(尽可能隐藏)来自IDE等
  • 通过CategorySerialized模式
  • ShouldSerialize*上使用条件序列化

答案 1 :(得分:4)

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

  

另一种选择是使用特殊模式创建XmlSerializer可识别的布尔字段,并将XmlIgnoreAttribute应用于该字段。该模式以propertyNameSpecified的形式创建。例如,如果有一个名为“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; }                   
}

除非您将魔术字段CategorySpecified设置为true,否则Category属性将不会被序列化。如果是反序列化,CategorySpecified将为false,表示XML中不存在Category

答案 2 :(得分:1)

完整的示例代码使用&#39;指定&#39;图案

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;

}