为什么在.NET 4中XmlDocument不是动态的?

svi*_*ick 10 xml dynamic c#-4.0

我希望看到使用的一个领域dynamic是XML.我认为它会使XML处理代码更容易编写,我相信在C#4出现之前我已经看到了一些例子,并且在这个答案中提到它是此功能的一个用途.

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

这对我来说更加奇怪,当我认为在PowerShell中,它XmlDocument 是动态的,代码就像$xmlDoc.root.subnode.subsubnode在那里工作一样.

mat*_*mc3 12

在没有答案的情况下,我对看似权威的讨论感到惊讶.你的问题很神奇.它完全解决了dynamic关键字所针对的那种令人敬畏的事情.麻烦的是,并没有很多人真正知道如何充分利用它.

虽然MS没有为我们构建动态XML对象,但它们确实为我们提供了使用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;
   }
}
Run Code Online (Sandbox Code Playgroud)

这就是你如何调用代码.请注意,这仅在C#4.0中编译.

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);
      }
   }
}
Run Code Online (Sandbox Code Playgroud)

我不能完全相信这一点. Bamboo在2003年为Boo 编写了这段代码 .C#已经慢慢获得了Boo多年来在.NET中拥有的功能......第一种类型的推理,现在是IQuackFu风格DynamicObject.一旦他们实现了语言宏以便你可以制作DSL,我认为他们已经赶上了.

我将把这个代码的新风格XElement版本留给读者.


jri*_*sta 6

鉴于一些评论,让我提供一个替代答案.最初的问题是为什么XmlDocument在.NET 4中不是动态的.虽然有可能通过现有的xml文档类添加"expando"属性功能IDynamicMetaObjectProvider这样做可能是一件非常重要的事情.使System.Xml中的原始Xml对象模型完全动态化需要对Xml框架进行一些大量修改,并且需要将IDynamicMetaObjectProvider添加到所涉及的每个对象中.这包括XmlDocument,XmlElement,XmlAttribute,XmlNode以及所有其他xml内容类型,如注释,文本节点等.此外,还有大量的支持基础结构,内部类型等,它们涉及查找和处理元素,属性和值也需要修改(打开Reflector,看看System.Xml ......超过一半的类型是内部的,它们彼此高度相互依赖,并且可用的公共类型.)

考虑在.NET中实现Xml的expando属性的适当范围也很重要.你会停止在XmlDocument和相关类型?或者包含XPath,Xml Schema等更合适吗?

为了回答原始问题,"为什么在.NET 4中没有动态的XmlDocument?",我认为简单的答案是:实现完全"动态"API,或者在Xml的情况下,提供任意属性扩展的API xml文档,远非繁琐的任务.鉴于微软的职业道德,从逻辑上讲,他们不会轻易接近这样的任务,如果他们试图为Xml框架实现expando属性,我希望并期望它能够以同样的谨慎关注和关注来完成他们给.NET的其余部分.