开发者

Is there a way to create an immutable (read-only) XDocument?

开发者 https://www.devze.com 2023-01-13 16:17 出处:网络
I have an API that returns XElement\'s, and I want the document behind those XElement\'s to be immutable (read-only). I need it for:

I have an API that returns XElement's, and I want the document behind those XElement's to be immutable (read-only). I need it for:

  • Not to give devs an ability to change it accidentally :)
  • Improving performance - creating a copy of an XDocument might be a performance "heavy" operation in some cases.

It doesn't seem to possible to inherit & override the necessary behavior in XDocument/XElement/XContainer, because all virtual methods there are marked as internal:

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

So my question is - is there a way make it happen, or it is better to have a different API that will either return something like XPathNavigator开发者_运维问答's, or it is better to have own classes like IReadOnlyXElement, etc.?


I doubt that the autor is still waiting for answers, but perhaps someone else will find it useful.

You can kind-of make the XDocument immutable by using its Changing event:

    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

Not the nicest solution, but it does provide a basic mechanism preventing accidental changes.


You could create an XElement wrapper that is similar to 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);
        }
    }
}


IMHO, it's probably better to make your own wrapper class for interacting with XDocuments/XElements. You can then limit the ability of a dev to write over the file in code.

I say limit because with enough information (location, schema (if needed)) a developer could use the stock XMLClasses to do whatever they wanted. The end all be all would be to make the file read-only on disk and make sure they (devs, users) do not have permission to change the read-only access on the file.

0

精彩评论

暂无评论...
验证码 换一张
取 消