7

我试图弄清楚如何将 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 文件中存在时,序列化/反序列化按预期工作。但是,如果CategoryXML 中缺少 ,则使用默认值(枚举中的第一项)。如果我尝试将枚举变量设为可空 ( Category?),则反序列化器会抛出异常,因为它无法反序列化复杂类型。给定以下 XML(不包含属性),我怎样才能适当地序列化枚举?

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

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

谢谢你尽你所能的帮助!

4

3 回答 3

14

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

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

这是做什么的:

  • 使用 aCategory?作为可选的枚举值
  • 禁用Category序列化的属性
  • 添加辅助属性 ,CategorySerialized作为 的代理Category,该属性不可为空并且从 IDE 等中隐藏(尽可能)
  • CategorySerialized通过ShouldSerialize*模式使用条件序列化
于 2012-05-31T20:12:03.043 回答
4

实际上,有一些官方的魔法可以做到这一点(见这里):

另一种选择是使用特殊模式来创建 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; }                   
}

除非您将魔法字段设置CategorySpecifiedtrue,否则Category属性不会被序列化。在反序列化的情况下,CategorySpecified将是false,表示CategoryXML 中不存在。

于 2013-12-01T19:42:30.417 回答
3

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

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;

}
于 2017-08-15T17:19:34.850 回答