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

发布于 2024-09-16 03:34:26 字数 668 浏览 6 评论 0原文

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

  • 不让开发人员能够意外更改它:)
  • 提高性能 - 在某些情况下,创建 XDocument 的副本可能是性能“繁重”的操作。

似乎不可能继承和重写 XDocument/XElement/XContainer 中的必要行为,因为那里的所有虚拟方法都标记为internal

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

所以我的问题是 - 有没有办法让它发生,或者最好有一个不同的 API,它要么返回类似 XPathNavigator 的东西,要么它最好拥有自己的类,例如 IReadOnlyXElement 等?

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 and 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.?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

陌伤ぢ 2024-09-23 03:34:26

我怀疑作者仍在等待答案,但也许其他人会发现它有用。

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

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

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.

挖鼻大婶 2024-09-23 03:34:26

您可以创建一个类似于 ReadOnlyCollectionXElement 包装器。

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);
        }
    }
}

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);
        }
    }
}
嘦怹 2024-09-23 03:34:26

恕我直言,最好创建自己的包装类来与 XDocuments/XElements 交互。然后,您可以限制开发人员在代码中重写文件的能力。

我说限制是因为有了足够的信息(位置、模式(如果需要)),开发人员就可以使用现有的 XMLClass 来完成他们想做的任何事情。最终的结果就是使文件在磁盘上只读,并确保他们(开发人员、用户)无权更改文件的只读访问权限。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文