Dot-Net

有沒有辦法創建不可變(只讀)XDocument?

  • April 8, 2013

我有一個返回XElement’s 的 API,我希望這些XElement’s 後面的文件是不可變的(只讀)。我需要它:

  • 不要讓開發人員能夠意外更改它:)
  • 提高性能 - 在某些情況下,創建副本XDocument可能是性能“繁重”的操作。

似乎不可能繼承和覆蓋 XDocument//XElement中的必要行為XContainer,因為那裡的所有虛擬方法都標記為internal

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

所以我的問題是 - 有沒有辦法讓它發生,或者最好有一個不同的 API 來返回類似XPathNavigator的東西,或者最好有自己的類IReadOnlyXElement,等等?

您可以創建一個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);
       }
   }
}

我懷疑作者是否仍在等待答案,但也許其他人會發現它有用。

您可以通過使用其更改事件使 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

不是最好的解決方案,但它確實提供了一種防止意外更改的基本機制。

引用自:https://stackoverflow.com/questions/3585120