有没有办法创建一个不可变(只读)的XDocument?

时间:2010-08-27 14:27:04

标签: .net api linq-to-xml xelement

我有一个返回XElement的API,我希望这些XElement后面的文档是不可变的(只读)。我需要它:

  • 不让devs有意识地改变它:)
  • 提高性能 - 在某些情况下,创建XDocument的副本可能是性能“繁重”的操作。

似乎无法继承&覆盖XDocument / XElement / XContainer中的必要行为,因为所有虚拟方法都标记为internal

internal virtual void XContainer.AddAttribute(XAttribute a)
{
}

所以我的问题是 - 有没有办法让它发生,或者最好是让一个不同的API返回像XPathNavigator这样的东西,或者最好拥有像{{IReadOnlyXElement这样的类。 1}}等等?

3 个答案:

答案 0 :(得分:12)

我怀疑autor还在等待答案,但也许其他人会发现它很有用。

您可以通过使用其Changing事件来使XDocument不可变:

    class Program
    {
        static void Main(string[] args)
        {
            var xdoc = XDocument.Parse("<foo id=\"bar\"></foo>");
            xdoc.Changing += (s, ev) =>
            {
                throw new NotSupportedException("This XDocument is read-only");
            };

            try
            {
                xdoc.Root.Attribute("id").Value = "boo";
            }
            catch (Exception e)
            {
                Console.WriteLine("EXCEPTION: " + e.Message);
            }

            Console.WriteLine("ID on exit: " + xdoc.Root.Attribute("id").Value);

            Console.ReadKey();
        }
    }

// Console output:
// EXCEPTION: This XDocument is read-only
// ID on exit: bar

不是最好的解决方案,但它确实提供了防止意外更改的基本机制。

答案 1 :(得分:4)

您可以创建一个与XElement类似的ReadOnlyCollection<T>包装器。

public sealed class ReadOnlyXElement
{
    private readonly XElement _element;


    public string Value
    {
        get { return _element.Value; }
    }


    public ReadOnlyXElement(XElement element)
    {
        _element = element;
    }


    public IEnumerable<ReadOnlyXElement> Elements()
    {
        foreach (var child in _element.Elements())
        {
            yield return new ReadOnlyXElement(child);
        }
    }

    public IEnumerable<ReadOnlyXElement> Elements(XName xname)
    {
        foreach (var child in _element.Elements(xname))
        {
            yield return new ReadOnlyXElement(child);
        }
    }
}

答案 2 :(得分:3)

恕我直言,制作自己的包装类可能更适合与XDocuments / XElements交互。然后,您可以限制开发人员在代码中写入文件的能力。

我说限制因为有足够的信息(位置,架构(如果需要)),开发人员可以使用股票XMLClasses来做任何他们想做的事情。最后一切都是在磁盘上使文件只读,并确保它们(开发者,用户)没有权限更改文件的只读访问权。