在反序列化上对字段添加约束

时间:2015-03-16 08:55:41

标签: c# xml xml-deserialization

在xsd架构中我已将属性Id定义为

<xs:attribute name="ID" type="xs:nonNegativeInteger" use="required"/>

但是,即使ID设置为大于UInt32.MaxValue的值,xml对xsd架构的验证也会通过。

我的反序列化代码如下所示:

var ser = new XmlSerializer(typeof(MyClass));
var settings = new XmlReaderSettings();
settings.ValidationFlags = XmlSchemaValidationFlags.ProcessInlineSchema | XmlSchemaValidationFlags.ProcessSchemaLocation | XmlSchemaValidationFlags.ProcessIdentityConstraints |    XmlSchemaValidationFlags.AllowXmlAttributes;
settings.ValidationType = ValidationType.Schema;
settings.Schemas.Add(_schemaNs, _schemaFileName);

var tReader = XmlReader.Create(filename, settings);
try
{
      var obj = ser.Deserialize(tReader) as MyClass;
}
catch(Excetion e)
{/*Process Validation exception.*/}

其中相应的变量如上所述。

MyClass的定义中我有:

    private uint idField;
    [System.Xml.Serialization.XmlAttributeAttribute()]
    public uint ID
    {

        get
        {               
            return this.idField;
        }
        set
        {
            this.idField = value;
        }
    }

现在,如果ID的值设置得太大,我希望XmlSerializer抛出异常。我想到的第一个想法是将MyClass中的ID字段类型设置为string并自行执行验证。然而,似乎有更优雅的方式来做到这一点。

2 个答案:

答案 0 :(得分:1)

我建议将不需要的值过滤的逻辑编码到反序列化中,而不是编码器本身,这可以按如下方式完成。

private uint idField;
[System.Xml.Serialization.XmlAttributeAttribute()]
public uint ID
{
    get
    {               
        return this.idField;
    }
    set
    {
        int SOME_BOUND = 10000;
        if (value > SOME_BOUND)
        {
            throw new ApplicationException();
        }
        this.idField = value;
    }
}

课程ApplicationException已记录在案hereArgumentOurOfBoundsException也可能适用。

答案 1 :(得分:1)

您可以通过这种方式在XSD架构中指定它:

<xs:attribute name="ID" use="required">
    <xs:simpleType>
        <xs:restriction base="xs:integer">
            <xs:minInclusive value="0"/>
            <xs:maxInclusive value="4294967295"/>
        </xs:restriction>
    </xs:simpleType>
</xs:attribute>

以下SO post也可能会有所帮助。