简体   繁体   English

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

[英]How to serialize/deserialize optional XML enumeration in C#?

I am trying to figure out how to serialize/deserialize an XML listing to C# that has an optional attribute that is an enumerated type. 我试图弄清楚如何将XML列表序列化/反序列化为具有可选属性(为枚举类型)的C#。 The following is my C# class: 以下是我的C#类:

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

    [XmlAttribute]
    public Category Category { get; set; }                   
}

My Category enumeration is defined as follows: 我的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
}  

When Category is present in the corresponding XML file, serialization/deserialization works as expected. 当相应的XML文件中存在Category ,序列化/反序列化将按预期方式工作。 However if the Category is missing from the XML, the default value is used (first item in the enumeration). 但是,如果XML中缺少Category ,则使用默认值(枚举中的第一项)。 If I try to make the enumerated variable nullable ( Category? ), the deserializer throws an exception because it is unable to deserialize a complex type. 如果我尝试使枚举变量可为空( Category? ),则反序列化器将引发异常,因为它无法反序列化复杂类型。 Given the following XML (which does not contain the attribute), how can I serialize the enumeration appropriately? 给定以下XML(不包含该属性),如何适当地序列化枚举?

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

In this situation, the value in the deserialized object should be null. 在这种情况下,反序列化对象中的值应为null。

Thanks for any help you can offer! 谢谢你的尽心帮助!

Well, you can do this - but it is a bit messy: 好吧,您可以执行此操作-但这有点混乱:

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

What this does: 这是做什么的:

  • uses a Category? 使用Category? for the optional enum value 用于可选的枚举值
  • disables the Category property for serialization 禁用Category属性以进行序列化
  • adds a secondary property, CategorySerialized , as a proxy to Category , which is non-nullable and hidden (as far as is possible) from the IDE etc 增加了一个二次性质, CategorySerialized ,作为一个代理来Category从IDE等,这是不可为空和隐藏(只要有可能)
  • use conditional serialization on CategorySerialized via the ShouldSerialize* pattern 通过ShouldSerialize*模式对CategorySerialized使用条件序列化

Actually, there's some official magic which allows to do this ( see here ): 实际上,有一些官方魔术可以做到这一点( 请参阅此处 ):

Another option is to use a special pattern to create a Boolean field recognized by the XmlSerializer, and to apply the XmlIgnoreAttribute to the field. 另一个选择是使用特殊的模式来创建XmlSerializer识别的布尔字段,并将XmlIgnoreAttribute应用于该字段。 The pattern is created in the form of propertyNameSpecified. 该模式以propertyNameSpecified的形式创建。 For example, if there is a field named "MyFirstName" you would also create a field named "MyFirstNameSpecified" that instructs the XmlSerializer whether to generate the XML element named "MyFirstName". 例如,如果存在一个名为“ MyFirstName”的字段,那么您还将创建一个名为“ MyFirstNameSpecified”的字段,该字段指示XmlSerializer是否生成名为“ MyFirstName”的XML元素。 This is shown in the following example. 在下面的示例中显示。

That is, the model in TS case should look like this: 也就是说,TS情况下的模型应如下所示:

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

    [XmlAttribute]
    public Category Category { get; set; }

    [XmlIgnore]
    public bool CategorySpecified { get; set; }                   
}

Unless you set magic field CategorySpecified to true , Category attribute won't be serialized. 除非将魔术字段CategorySpecified设置为true ,否则不会对Category属性进行序列化。 In case of deserialization, CategorySpecified will be false , indicating that Category wasn't present in XML. 在反序列化的情况下, CategorySpecified将为false ,指示在XML中不存在Category

The complete sample code using 'Specified' pattern 使用“指定”模式的完整示例代码

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;

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM