<?xml version="1.0" encoding="utf-8" ?>
<pages>
<page id="56">
<img id="teaser" src="img/teaser_company.png"></img>
</page>
</pages>
我有一个xml文件,它为cms中的页面定义了额外的资源。使用LinqToXml查询此文件时,保护Null Reference异常的最佳方法是什么?
var page = (from tabElement in extensionsDoc.Descendants("page")
where tabElement.Attribute("id").Value == tabId.ToString()
select tabElement).SingleOrDefault();
如果页面元素没有名为“id”的属性,则此代码可能会触发Null Reference异常。我是否必须使用try catch块或有办法处理这个问题?例如,如果页面元素没有名为“id”的属性,则为页面对象返回null。
答案 0 :(得分:28)
最简单的方法是:
var page = (from tabElement in extensionsDoc.Descendants("page")
let idAttribute = tabElement.Attribute("id")
where idAttribute != null
&& idAttribute.Value == tabId.ToString()
select tabElement).SingleOrDefault();
或者,您可以将扩展方法写入XElement
:
public static string AttributeValueOrDefault(this XElement element,
string attributeName)
{
XAttribute attr = element.Attribute(attributeName);
return attr == null ? null : attr.Value;
}
然后使用:
var page = (from element in extensionsDoc.Descendants("page")
where element.AttributeValueOrDefault("id") == tabId.ToString()
select element).SingleOrDefault();
或使用点符号:
var page = extensionsDoc.Descendants("page")
.Where(x => x.AttributeValueOrDefault("id") == tabId.ToString())
.SingleOrDefault();
(事先调用tabId.ToString()
,btw,而不是每次迭代都是有意义的。)
答案 1 :(得分:10)
在.NET 4中,LINQ to XML提供了一种方法,它使用explicit casts:
var page = (
from tabElement in extensionsDoc.Descendants("page")
where (string)tabElement.Attribute("id") == tabId.ToString()
select tabElement
).SingleOrDefault();
如果属性不存在,则结果将为空。
除了显式string
运算符之外,还有大多数基本类型及其Nullable版本。这意味着您可以使用以下语法执行AttributeOrDefault
:
//<element theAttr="12" />
int theAttr = (int?)doc.Element("element").Attribute("missingAttr") ?? 0;
答案 2 :(得分:3)
我以前见过其他人也使用直接演员来演奏弦乐;我不知道它的效率是否比Jon建议的更高或更低,但我非常喜欢语法。
var page = extensionsDoc.Descendants("page")
.Where(x => (string)x.Attribute("id") == tabId.ToString())
.SingleOrDefault();
如果我的思想存在一些缺陷,任何人都可以随意解决这个问题。我对LINQ很新。
答案 3 :(得分:1)
我倾向于使用XPath表达式,否则代码会被大量的空检查混乱。以你的例子:
var query = string.Format("page[@id='{0}']", tabId.ToString());
var page = extensionsDoc.XPathSelectElement(query);
答案 4 :(得分:0)
我会使用一个映射XML元素的类实体。并调用一个检查null值的方法。我在我的代码中使用此方法,它工作正常。希望它有所帮助。
以下是根据您的需求进行调整的示例代码:
private void Method1(...) {
...
var pages = from tabElement in extensionsDoc.Descendants("page")
where tabElement.Attribute("id").Value == tabId.ToString()
select new Page {
imgSrc = Method2(tabElement)
};
// pages variable is a List<Page> object
...
}
private void Method2(XElement element) {
XElement img = element.Element("img");
if (img != null) {
...
// TODO return the imgSrc
return "";
}
// return null or ""
return null;
}
然后是Page类定义:
class Page
{
public string imgSrc { get; set; }
}