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.
精彩评论