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:
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);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With