2011-02-24 109 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