Почему XmlDocument не работает в .NET 4?

Одна из областей, где я хотел бы использовать dynamic, - это XML. Я думаю, что это упростило бы код обработки XML, и я считаю, что я видел несколько примеров этого, прежде чем С# 4 вышел, и он упомянул в этом ответе как одно из применений этой функции.

Итак, мой вопрос заключается в следующем: почему не был создан XmlDocument (или XDocument) динамический или почему нет нового класса для динамического XML-манипулирования в С# 4?

Это еще более странно для меня, когда я считаю, что в PowerShell XmlDocument является динамическим, там работает код $xmlDoc.root.subnode.subsubnode.

Ответ 1

Учитывая некоторые из комментариев, позвольте мне предоставить альтернативный ответ. Первоначальный вопрос задал вопрос о том, почему XmlDocument не был динамическим в .NET 4. Хотя возможно добавить свойство "expando" для существующих классов документов xml через IDynamicMetaObjectProvider, это, вероятно, является нетривиальным делом. Для того чтобы исходная объектная модель Xml из полностью динамической системы System.Xml потребовала некоторой обширной модификации инфраструктуры Xml и потребовала бы, чтобы IDynamicMetaObjectProvider был добавлен к каждому объекту, который задействован. Это включает XmlDocument, XmlElement, XmlAttribute, XmlNode и все другие типы содержимого xml, такие как комментарии, текстовые узлы и т.д. Кроме того, значительное количество инфраструктуры поддержки, внутренних типов и т.д., Которые участвуют в поиске и обработке элементы и атрибуты и значения также должны быть изменены (откройте Reflector и взгляните на System.Xml... более половины типов являются внутренними, и все они очень взаимозависимы друг с другом и доступными общедоступными типами.)

Также важно рассмотреть правильную область применения свойств expando для Xml в .NET. Вы остановились бы только на XmlDocument и связанных с ним типах? Или было бы более целесообразным включить XPath, Xml Schema и т.д.?

Чтобы ответить на исходный вопрос: "Почему isnt XmlDocument dynamic в .NET 4?", я думаю, что простой ответ таков: реализация полностью "динамических" API или, в случае с Xml здесь, API, которые обеспечивают расширение свойств произвольные xml-документы, далеки от тривиальной задачи. Учитывая этику работы Microsoft, логично понять, что они не будут легко подходить к такой задаче, и если они попытаются реализовать свойства expando для инфраструктуры Xml, я надеюсь и ожидаю, что это будет сделано с таким же вниманием и вниманием они дают остальной части .NET.

Ответ 2

Я удивлен количеством кажущейся авторитетной дискуссии без ответа. Ваш вопрос FANTASTIC. В нем конкретно рассматриваются такие удивительные вещи, для которых предназначалось ключевое слово 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;
   }
}

И вот как бы вы назвали код. Обратите внимание, что это компилируется только в С# 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);
      }
   }
}

Я не могу взять на себя все это. Bamboo написал этот код для Boo еще в 2003 году. С# медленно получал функции, которые Boo имел в .NET в течение многих лет... сначала тип, а теперь стиль IQuackFu DynamicObject. Как только они реализуют языковые макросы, чтобы вы могли создавать DSL, я думаю, что они поймают.

Я оставлю запись читателю новой версии XElement этого кода читателю.

Ответ 3

Скорее всего, они об этом не думали, и программисты обычно не сбивают с толку динамику повсюду: динамика - это бомба замедленного действия. Поймайте столько, сколько сможете во время компиляции...

Ответ 4

Поскольку XmlDocument предшествует genereics и исправлению, он сломает старый код.

Кроме того, XmlDocument указан как полууниверсальный.