如果在C#中未找到一个元素,我能否使用XmlSerializer反序列化失败?

15

我正在使用XmlSerializer在C#中将对象写入和读取到xml。我目前使用属性XmlElementXmlIgnore来操作对象的序列化。

如果我的xml文件缺少我需要的xml元素,我的对象仍然可以正常反序列化(xml->对象)。如何指示(最好通过属性)某个字段是“必需的”?

以下是我目前正在使用的示例方法:

[XmlElement(ElementName="numberOfWidgets")]
public int NumberThatIsRequired {
    set ...;
    get ...;
}

我理想的解决方案是添加类似于 XmlRequired 属性。

此外,是否有好的参考资料可以操作 XmlSerializer 的行为属性?

我的理想解决方案是添加类似于XmlRequired属性。同时,是否有可用于操纵 XmlSerializer 行为的属性的良好参考资料?


这里有一个类似的MSDN问题链接,它也解释了验证是您正在尝试做的事情。 - KCD
如果XML中没有元素numberOfWidgets,那么属性NumberThatIsRequired会是什么?零吗? - Louis Rhys
3个回答

16
我发现唯一的方法是通过XSD。您可以在反序列化时进行验证:
static T Deserialize<T>(string xml, XmlSchemaSet schemas)
{
    //List<XmlSchemaException> exceptions = new List<XmlSchemaException>();
    ValidationEventHandler validationHandler = (s, e) =>
    {
        //you could alternatively catch all the exceptions
        //exceptions.Add(e.Exception);
        throw e.Exception;
    };

    XmlReaderSettings settings = new XmlReaderSettings();
    settings.Schemas.Add(schemas);
    settings.ValidationType = ValidationType.Schema;
    settings.ValidationEventHandler += validationHandler;

    XmlSerializer serializer = new XmlSerializer(typeof(T));
    using (StringReader sr = new StringReader(xml))
        using (XmlReader books = XmlReader.Create(sr, settings))
           return (T)serializer.Deserialize(books);
}

5
我已经为第二部分找到了答案:“控制XML序列化的属性”
还在调查第一部分...
编辑:我强烈怀疑你不能通过XML反序列化本身来完成这个任务。我刚刚在一个包含必需属性的样例模式上运行了xsd.exe,如果将该属性标记为可选,则完全相同。如果有一种方法可以要求设置属性,我希望它能在那种情况下实现。
我怀疑你基本上只能在反序列化后验证对象树。对此感到抱歉...

您需要在源XML中正确设置XML命名空间,并在XSD中引用它,否则使用XSD进行验证将无法正常工作,包括必填字段验证。 - Robert Harvey

4
为了提高可扩展性,XmlSerializer在反序列化时非常宽容;像[DefaultValue]ShouldSerialize{Foo}{Foo}Specified这样的东西主要用于序列化(例外是{Foo}Specified,在反序列化期间设置并在序列化期间查询)。
因此,除非您自己实现IXmlSerializable,否则没有容易的方法来执行此操作。Richard展示了一种xsd选项,这也是一种选项。

1
DefaultValue在反序列化期间至少有一个重要的影响。如果元素为空且没有设置DefaultValue,则可能会出现解析错误。但是,如果设置了DefaultValue,则生成的代码将跳过空元素。 - Matthew Flaschen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接