2009-04-27 24 views
12
<?xml version="1.0" encoding="utf-8" ?> 
<pages> 
    <page id="56"> 
    <img id="teaser" src="img/teaser_company.png"></img> 
    </page> 
</pages> 

Tôi có tệp xml xác định tài nguyên bổ sung cho các trang trong một cm. Cách tốt nhất để bảo vệ ngoại lệ tham chiếu Null khi truy vấn tệp này bằng LinqToXml là gì?Làm thế nào để bạn bảo vệ cho ngoại lệ tham chiếu Null trong LINQ To Xml?

var page = (from tabElement in extensionsDoc.Descendants("page") 
where tabElement.Attribute("id").Value == tabId.ToString() 
select tabElement).SingleOrDefault(); 

Mã này có thể kích hoạt ngoại lệ tham chiếu Null nếu phần tử trang không có thuộc tính được gọi là "id". Tôi có phải sử dụng khối try try hoặc có cách nào để xử lý việc này không? Ví dụ trả về null cho trang đối tượng trang nếu không có thuộc tính được gọi là "id" cho phần tử trang.

+0

Làm thế nào về việc kiểm tra trả trước các tabId? –

Trả lời

28

EDIT: Điều này đã được viết rõ ràng từ lâu rồi - những ngày này tôi chắc chắn sẽ đi với dàn diễn viên theo câu trả lời của Igor.

Cách đơn giản nhất sẽ là một cái gì đó như:

var page = (from tabElement in extensionsDoc.Descendants("page") 
      let idAttribute = tabElement.Attribute("id") 
      where idAttribute != null 
        && idAttribute.Value == tabId.ToString() 
      select tabElement).SingleOrDefault(); 

Hoặc bạn có thể viết một phương pháp khuyến nông để XElement:

public static string AttributeValueOrDefault(this XElement element, 
              string attributeName) 
{ 
    XAttribute attr = element.Attribute(attributeName); 
    return attr == null ? null : attr.Value; 
} 

sau đó sử dụng:

var page = (from element in extensionsDoc.Descendants("page") 
      where element.AttributeValueOrDefault("id") == tabId.ToString() 
      select element).SingleOrDefault(); 

Hoặc sử dụng dấu chấm ký hiệu:

var page = extensionsDoc.Descendants("page") 
      .Where(x => x.AttributeValueOrDefault("id") == tabId.ToString()) 
      .SingleOrDefault(); 

(Nó sẽ làm cho tinh thần để gọi tabId.ToString() lần trước, btw, chứ không phải cho mỗi lần lặp.)

+0

Phương pháp mở rộng sẽ chỉ hoạt động nếu bạn không cần thuộc tính của thuộc tính, như độ dài của nó. 'x.AttributeValueOrDefault (" id "). Length> 0' chẳng hạn sẽ vẫn ném NullReferenceException. Tôi nghĩ việc sử dụng 'let' an toàn hơn. _BTW, tiếc là ReSharper không cảnh báo về một NullReferenceEception có thể nếu bạn use_ 'let' _and không kiểm tra for_' null'. – comecme

+0

@comecme: Trong trường hợp đó bạn có thể sử dụng toán tử kết hợp null. Nó không phải là một thuốc chữa bách bệnh ... mặc dù sử dụng các diễn viên rõ ràng sẽ thực sự tốt hơn ở đây. –

3

tôi đã nhìn thấy người khác sử dụng một dàn diễn viên thẳng đến một chuỗi trước cũng; Tôi không biết liệu nó có hiệu quả hơn hay ít hiệu quả hơn những gì Jon đề xuất, nhưng tôi khá thích cú pháp.

var page = extensionsDoc.Descendants("page") 
      .Where(x => (string)x.Attribute("id") == tabId.ToString()) 
      .SingleOrDefault(); 

Bất cứ ai cũng cảm thấy tự do để khắc phục điều đó nếu có một số sai sót trong suy nghĩ của tôi; Tôi khá mới với LINQ.

1

Tôi có xu hướng sử dụng các biểu thức XPath nơi mã sẽ bị lộn xộn với nhiều kiểm tra null. Ví dụ của bạn:

var query = string.Format("page[@id='{0}']", tabId.ToString()); 
var page = extensionsDoc.XPathSelectElement(query); 
10

Trong .NET 4 LINQ to XML cung cấp một cách để làm điều đó và nó là thông qua sử dụng explicit casts:

var page = (
    from tabElement in extensionsDoc.Descendants("page") 
    where (string)tabElement.Attribute("id") == tabId.ToString() 
    select tabElement 
).SingleOrDefault(); 

Nếu thuộc tính là không có, thì kết quả sẽ chỉ đơn giản không có giá trị.

Ngoài nhà điều hành rõ ràng string cũng có hầu hết các loại nguyên thủy và các phiên bản không thể bỏ qua của chúng. Điều này có nghĩa là bạn có thể làm AttributeOrDefault bằng cách sử dụng loại cú pháp này:

//<element theAttr="12" /> 
int theAttr = (int?)doc.Element("element").Attribute("missingAttr") ?? 0; 
+2

Ví dụ cuối cùng của bạn có thể là trường hợp NullReferenceException nếu không có Element '" element "' tồn tại. – comecme

0

Tôi sẽ sử dụng thực thể lớp ánh xạ phần tử XML. Và gọi một phương thức sẽ kiểm tra giá trị null. Tôi sử dụng phương pháp này trong mã của tôi, nó hoạt động tốt. Hy vọng nó giúp.

Dưới đây là một số mẫu mã để điều chỉnh tùy thuộc vào nhu cầu của bạn:

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; 
} 

Sau đó định nghĩa trang lớp:

class Page 
{ 
    public string imgSrc { get; set; } 
} 
+0

Nếu 'tabElement' không có thuộc tính' "id" ', điều đó sẽ vẫn gây ra một NullReferenceException trong' Method1' của bạn. – comecme

Các vấn đề liên quan