检查XElement是否全局为null

时间:2011-10-26 07:10:24

标签: c# .net xml linq-to-xml

我有一个负责读取和保存XML文件的类。 现在它的简单版本如下所示:

public class EstEIDPersoConfig
{
    public bool LaunchDebugger { get ; set; }
    public string Password { get; set; }
    public int Slot { get; set; }
    public string Reader { get; set; }
    public string TestInput { get; set; }
    public bool Logging { get; set; }

    public EstEIDPersoConfig()
    {
        XElement xml = XElement.Load(myxml.xml);
        XElement Configuration = xml.Element("Configuration");

        LaunchDebugger = Convert.ToBoolean(Configuration.Element("LaunchDebugger").Value);
        Password = Configuration.Element("Password").Value;
        Slot = Convert.ToInt32(Configuration.Element("Slot").Value);
        Reader = Configuration.Element("Reader").Value;
        TestInput = Configuration.Element("TestInput").Value;
        Logging = Convert.ToBoolean(Configuration.Element("Logging").Value);
     }
 }

稍后会有更多。所以问题是如果xml中不存在某个元素我得System.NullReferenceException。所以我需要检查元素是否为null。这是一种方法:

var value = Configuration.Element("LaunchDebugger").Value;
if (value != null)
    LaunchDebugger = Convert.ToBoolean(value);
else
    throw new Exception("LaunchDebugger element missing from xml!");

但是为每个元素做这件事太过分了。所以我需要一些好的想法如何简化这个系统,以便它不会以1000行代码结束。

编辑:编辑了最后一段代码片段,想法是不设置默认值,想法是通知用户xml中缺少此元素为空。

6 个答案:

答案 0 :(得分:4)

(bool)Configuration.Element("LaunchDebugger")

(bool?)Configuration.Element("LaunchDebugger")

不应该抛出异常。

请参阅MSDN:

答案 1 :(得分:4)

这里的想法直接来自abatischev的回答,所以他值得赞扬。

正如Microsoft here所述,您可以将XElement转换为您想要的类型。

LaunchDebugger = (bool?)Configuration.Element("LaunchDebugger");

如果你想处理null案件,我想你可以做到

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? true);

或者

LaunchDebugger = (bool)(Configuration.Element("LaunchDebugger") ?? false);

取决于您的业务逻辑。如果你为特定类型做同样的聚结,可能适合用方法,扩展或其他方式包装这个衬垫,但我不确定它会增加很多。

答案 2 :(得分:2)

将逻辑解压缩到一个方法,并为Int32,boolean和其他数据类型转换重载方法。

public static void GetElementValue(XElement xElement, string parameter, out bool value)
    {
        var stringValue = xElement.Element(parameter).Value;
        value = false;
        if (value != null)
            value = Convert.ToBoolean(stringValue);
    }

答案 3 :(得分:2)

我有一个扩展方法,我只是用这种东西:

    public static T GetValue<T>(
            this XElement @this,
            XName name, 
            Func<XElement, T> cast, 
            Func<T> @default)
    {
        var e = @this.Element(name);
        return (e != null) ? cast(e) : @default();
    }

它为您提供所需的铸造以及默认值工厂。

以下是您使用它的方式:

LaunchDebugger = Configuration.GetValue("LaunchDebugger",
    x => Convert.ToBoolean(x), () => false);
Password = Configuration.GetValue("CMKPassword", x => (string)x, () => "");
Slot = Configuration.GetValue("CMKSlot", x => (int)x, () => -1);
Reader = Configuration.GetValue("Reader", x => (string)x, () => "");
TestInput = Configuration.GetValue("TestInput", x => (string)x, () => "");
Logging = Configuration.GetValue("Logging",
    x => Convert.ToBoolean(x), () => false);

答案 4 :(得分:1)

外部方法怎么样:

public static class XElementExtensions
{
    public static bool AsBoolean(this XElement self, bool defaultValue)
    {
        if (self == null)
        {
            return defaultValue;
        }
        if (!string.IsNullOrEmpty(self.Value))
        {           
            try
            {
                return XmlConvert.ToBoolean(self.Value);
            }
            catch
            {
                return defaultValue;
            }
        }
        return defaultValue;
    }
}

我已经使用SnippetCompiler进行了测试:

XElement test = new XElement("test", 
    new XElement("child1"),
    new XElement("child2", new XText("true")),
    new XElement("child3", new XText("false")),
    new XElement("child4", new XText("rubbish")));

WL(test.Element("child1").AsBoolean(false)); // note, "child1" has no value (or is `""`)
WL(test.Element("child2").AsBoolean(false));
WL(test.Element("child3").AsBoolean(false));
WL(test.Element("child4").AsBoolean(false));
WL(test.Element("child5").AsBoolean(false)); // note, "child5" doesn't exist        

产生这个结果:

False
True
False
False
False

为其他类型添加更多此类方法,并添加AsBoolean(defaultValue),因为当您希望默认为true时,它可以派上用场!

正如其他人所说,您可以使用??运算符为null提供值。但是,这不会嵌套:

LaunchDebugger = XmlConvert.ToBoolean(Configuration.Element("LaunchDebugger").Value) ?? false;
如果XML文件中没有这样的元素,

将通过NullReferenceException

答案 5 :(得分:1)

您可以定义一个方法来为您提取值,并在那里检查null。因此,将值检索包装在您自己的方法中,如下所示:

public string GetXMLValue(XElement config, string elementName){
    var element = Configuration.Element(elementName);

    if(element == null)
        return String.Empty;

    return element.Value;
}

当然,你可以通过解析为boolean等来扩展它以正常工作。