代码之家  ›  专栏  ›  技术社区  ›  svick Raja Nadar

为什么.NET4中的XmlDocument不是动态的?

  •  10
  • svick Raja Nadar  · 技术社区  · 15 年前

    我希望看到 dynamic 是XML。我认为这会使XML处理代码的编写更简单,而且我相信在C#4出现之前,我已经看到了一些例子 in this answer 作为此功能的用途之一。

    所以,我的问题是:为什么 XmlDocument (或 XDocument )或者为什么在C#4中没有用于动态XML操作的新类?

    这对我来说更奇怪,当我在PowerShell中考虑到这一点时, XML文档 是动态的 ,代码类似 $xmlDoc.root.subnode.subsubnode

    4 回复  |  直到 8 年前
        1
  •  6
  •   jrista    15 年前

    鉴于一些评论,让我提供另一种答案。最初的问题是为什么XmlDocument在.NET4中不是动态的,而通过 IDynamicMetaObjectProvider ,这样做可能是一个不小的努力。要使System.Xml中的原始Xml对象模型完全动态,需要对Xml框架进行一些广泛的修改,并且需要将IDynamicMetaObjectProvider添加到所涉及的每个对象中。它包括XmlDocument、XmlElement、XmlAttribute、XmlNode和所有其他xml内容类型,如注释、文本节点等。此外,还有大量的支持基础结构、内部类型,在元素、属性和值的查找和处理过程中涉及到的其他类型也需要修改(打开Reflector,看看System.Xml…超过一半的类型是内部的,它们彼此之间以及可用的公共类型之间高度依赖。)

    考虑在.NET中为Xml实现expando属性的适当范围也很重要。您能不能只看一下XmlDocument和相关类型?或者包含XPath、xmlschema等更合适吗。?

    要回答最初的问题“为什么.NET4中的XmlDocument不是动态的?”,我认为简单的答案是:实现完全“动态”的API,或者在这里的Xml中,提供任意Xml文档属性扩展的API,远不是一项简单的任务。考虑到微软的职业道德,他们不会轻易完成这样一项任务是合乎逻辑的,如果他们试图为Xml框架实现expando属性,我希望并期望他们能像对待.NET的其他部分一样小心地完成这项任务。

        2
  •  12
  •   mattmc3    11 年前

    我很惊讶有这么多看似权威的讨论却没有答案。你的问题太棒了。它正好解决了 dynamic 关键字的目的。问题是,不是很多人真的知道如何充分利用它。

    DynamicObject 班级。这里有一种方法可以满足你对老朋友的要求 XmlDocument 班级。

    public class DynamicXmlElement : DynamicObject {
       XmlElement _xmlEl;
    
       public DynamicXmlElement(string xml) {
          var xmldoc = new XmlDocument();
          xmldoc.LoadXml(xml);
          _xmlEl = xmldoc.DocumentElement;
       }
    
       public DynamicXmlElement(XmlElement el) {
          _xmlEl = el;
       }
    
       public override bool TrySetMember(SetMemberBinder binder, object value) {
          return false;
       }
    
       public override bool TryGetMember(GetMemberBinder binder, out object result) {
          XmlElement el = (XmlElement)_xmlEl.SelectSingleNode(binder.Name);
          if (el != null) {
             // wrap the element we found in a new DynamicXmlElement object
             result = new DynamicXmlElement(el);
             return true;
          }
          else if (binder.Name == "root") {
             // special case for handling references to "root"
             result = new DynamicXmlElement(_xmlEl.OwnerDocument.DocumentElement);
             return true;
          }
          else {
             // feel free to change this to prevent having accidental null reference issues
             // by just setting the result to a DynamicXmlElement with a null element and 
             // handling _xmlEl == null at the start of this method
             result = null;
             return false;
          }
       }
    
       public override string ToString() {
          return _xmlEl.InnerText;
       }
    }
    

    namespace ConsoleApplication4 {
       class Program {
          static void Main(string[] args) {
             var xmlstr = "<r><subnode><subsubnode>ABCs of dynamic classes</subsubnode></subnode></r>";
             dynamic xml = new DynamicXmlElement(xmlstr);
             Console.WriteLine(xml.subnode.root.subnode.subsubnode); // take the long way around...
             Console.ReadKey(true);
          }
       }
    }
    

    我不能把所有的功劳都归功于这件事。 Bamboo wrote this code 早在2003年,对于Boo来说,C#已经慢慢地获得了Boo多年来在.NET中拥有的功能。。。先是类型推断,现在是伊萨克福风格 DynamicObject . 一旦他们实现了语言宏,这样你就可以制作dsl了,我想他们会赶上的。

    我将把编写这段代码的新样式XElement版本留给读者。

        3
  •  -1
  •   Pavel Radzivilovsky    15 年前

    最有可能的是他们还没有考虑过,而且,程序员通常不喜欢把动态放在所有地方:动态是一个定时炸弹。在编译时尽可能多地捕获。。。

        4
  •  -2
  •   Joshua    15 年前

    另外,XmlDocument被列为半过时。