C#Xml反序列化加设计建议

时间:2013-02-08 07:57:24

标签: c# xml xmlserializer xml-deserialization

在我的项目中,我需要构建一个应该向后兼容的通用反序列化器。 示例:XML看起来像

<PolicyDef name = "sample" type="type1">
  <Options ......>
</PolicyDef>

“type”是枚举 - PolicyTypes 例如

public Enum PolicyTypes
{
 type1 = 0,
 type2 = 1
}

PolicyDef类定义为

[XmlRoot("PolicyDef")]
    public class PolicyDef
    {
        private string policyName;
        private PolicyTypes policyType;

        public PolicyDefinition()
        {         
        }

        [XmlAttribute]
        public string Name
        {
            get
            {
                return this.policyName;
            }
            set
            {
               this.policyName = value;

            }
        }      
        [XmlAttribute]
        public PolicyTypes Type
        {
            get
            {
                return this.policyType;
            }
            set
            {
               this.policyType = value;

            }
        }           
    }

这种方法的问题在于,如果稍后我放置除类型1或类型2之外的任何类型,XMLDeserializer将抛出异常。 所以,如果我有像

这样的xml
<PolicyDef name = "sample" type="type_new">
  <Options ......>
</PolicyDef>

如果type_new无效,则反序列化器将抛出错误。

我想知道是否有办法挂钩反序列化程序进程来捕获它并设置默认值而不是抛出错误。如果有任何无效值,我会将其设置为“type1”

或者对如何处理此问题的建议持开放态度

谢谢和问候

2 个答案:

答案 0 :(得分:0)

这可能是C# XML Deserialization W/ Default Values

的副本

不幸的是,在反序列化期间似乎无法回退默认的枚举值。它需要稍微多一些工作,但是如果您按照链接的示例并在PolicyDef类中实现IXmlSerializable,您将能够以类似的方式实现ReadXml方法(使用try / catch块按顺序反映每个属性)检查默认值。)

希望有所帮助!

答案 1 :(得分:0)

感谢Chris的建议,但我不想最终编写完整的解析代码,如果XML和相应的类庞大而复杂,这可能会很麻烦。无论如何我使用了不同的方法。 我将所有枚举字段更改为字符串。在这种情况下,不存在解析错误,然后公开另一个属性,该属性将解析的值作为枚举返回,如果解析失败,则返回默认的枚举值。 E.g

private string policyName;
[XmlAttribute("Type")]
public string Type
{
    private get
    {
        return this.policyType;
    }
    set
    {
        this.policyType = value;
        try
        {
            this.PolicyType = (PolicyTypes)Enum.Parse(typeof(PolicyTypes), this.policyType);
        }
        catch(Exception)
        {
            this.PolicyType = PolicyTypes.DefaultPolicy;
        }
    }
}

public PolicyTypes PolicyType
{
    get;
    private set;
}

并使用class属性来访问值而不是xml属性字段。