2011-02-24 95 views
0

我在寫一個叫做的類,其類別爲,它有兩個靜態方法用於從外部資源中檢索XML數據。在我下面的例子中,我只會展示一個,因爲它們非常相似。這個XDocument代碼是否安全?

我想知道的是,無論這個代碼是無效的URL,無效的數據等等,這個代碼是否是「安全的」。基本上使它更加健壯。 這裏是德碼

private static string XmlUri 
    { 
     get { return "path-to-xml-file"; } 
    } 
private static XDocument XmlFile { get; set; } 
public int ID { get; set; } 
public string Name { get; set; } 
public int Parent { get; set; } 

/// <summary> 
/// Gets a specific category 
/// </summary> 
/// <param name="id"></param> 
/// <returns>A Category with the specified ID</returns> 
public static Category Get(int id) 
{ 
    try 
    { 
     if (XmlFile == null) 
      XmlFile = XDocument.Load(XmlUri); 
    } 
    // Invalid URL or data 
    catch (Exception ex) 
    { 

     // TODO: Log exception 
     Console.WriteLine(ex.Message); 
    } 

    if (XmlFile == null) 
     return null; 

    var cat = from category in XmlFile.Descendants("Category") 
       where category.Attribute("id").Value.ParseSafe() == id 
       select new Category 
       { 
        ID = category.Attribute("id").Value.ParseSafe(), 
        Parent = category.Attribute("parent").Value.ParseSafe(), 
        Name = category.Value 
       }; 

    return cat.SingleOrDefault(); 
} 
+1

您對外部XML有多少控制?您可能需要根據模式對其進行驗證。此外,您的代碼可能爆炸*(要使用技術術語...)*當多個線程嘗試讀取XML時。 – ChaosPandion 2011-02-24 21:52:01

+0

@Chaos - 我無法控制XML文件,所以我必須使用我所擁有的。你能不能解釋一下線程安全部分,聽起來不像我會遇到這種情況,但要確定。謝謝! – Marko 2011-02-25 00:12:30

回答

1

定義 '安全'。出現問題時,您的代碼將生成null。我會考慮在XDocument.Load()之後的catch塊中(重新)拋出。爲了安全,請在而不是忽略無效的URL。

而且,ParseSafe()和SingleOrDefault也會出現問題。如果id缺失或格式錯誤,您希望發生什麼?

而且,一個小改進:您可以將按需加載邏輯放入XmlFile的getter中。如果您還希望在類別旁邊添加其他元素,則會更輕鬆。

+0

+1:用於「返回null」行爲。呼叫者可能不會期待這一點。 – 2011-02-24 22:12:22

+0

Thanks @Henk,如果發生任何錯誤,我將返回null,而使用此類的應用程序的其他部分將在執行任何其他工作之前檢查null。 ParseSafe方法只是一個字符串擴展,它使用int.TryParse返回一個整數,如果無效則返回0。我假設SingleOrDefault也會返回null,如果沒有找到我實際上瞄準的匹配的話。至於按需加載邏輯,你的意思是這樣嗎? 'private static XDocument XmlFile {get {return {XDocument.Load(XmlUri);}}' – Marko 2011-02-25 00:10:27

+0

如果您的調用者不關心「沒有結果」和「提供者爆炸」之間的區別,那麼就可以。我的意思是在吸氣器內有一個「if x!= null」。 – 2011-02-25 08:22:16

1

不像ChaosPandion提到的那樣線程安全。

混淆性能行爲 - Get(int)看起來像簡單的快速方法,但實際上涉及非平凡的工作。使用延遲初始化並將類別onece的整個集合讀入字典。

不應該捕獲異常併吞下它 - 要麼使用特定的(在這種情況下我認爲是IOException和XMLExcepetion),要麼至少讓致命的異常被正常拋出。

顯然,如果你不控制XML文件,它也可能導致緩慢/掛起時加載瘋狂的大文件。取決於閱讀器的行爲和XML的複雜性(如果惡意方給予您的),可能會導致一些其他異常,如StackOverflow導致您的進程中斷。

+0

嗨@Alexei對於我遲到的迴應感到抱歉,我剛剛開會。我實際上**不**不能控制XML文件。你能否更詳細地解釋一下線程安全部分,這個想法是我只加載一次XML文件並將其存儲在內存中以便多次使用......該應用程序是一個控制檯應用程序,它將被安排在一定的時間和填充數據庫,所以只會有一個foreach循環遍歷節點並將它們添加到數據庫中,這是否會導致線程安全問題? – Marko 2011-02-24 23:59:28

+0

如果您的控制檯應用程序不涉及創建線程或其他explcit異步處理(即QueueUserWorkItem),則不需要擔心代碼的線程安全性。如果您從多個線程中調用方法,則需要擔心在訪問非不可變結構時線程之間的同步(即,無法保證XDocument方法同時可以安全地從多個線程進行訪問,而Dictionary允許這樣的訪問沒有修改)。搜索「編寫線程安全代碼」以查找信息... – 2011-02-25 01:14:48

+0

「我不控制XML」 - 如果您期望惡意XML或只是無效,那麼這更像是一個問題。以後更容易處理,並且您的代碼適用於在友好環境中運行的非公共工具。 – 2011-02-25 01:16:38