2010-06-23 44 views
10

Một trong những lĩnh vực mà tôi muốn thấy việc sử dụng dynamic là XML. Tôi nghĩ rằng nó sẽ làm cho mã xử lý XML đơn giản hơn để viết và tôi tin rằng tôi đã thấy một số ví dụ về điều đó trước khi C# 4 xuất hiện và nó được đề cập đến in this answer là một trong những công dụng của tính năng này. Vì vậy, câu hỏi của tôi là: tại sao không phải là XmlDocument (hoặc XDocument) làm động, hoặc tại sao không có một số lớp mới cho thao tác XML động trong C# 4?Tại sao không phải là XmlDocument động trong .NET 4?

này thậm chí còn kỳ lạ hơn với tôi, khi tôi xem xét rằng trong PowerShell, XmlDocumentlà động, mã như $xmlDoc.root.subnode.subsubnode công trình đó.

+5

Nếu bất kỳ loại nào sẽ bị thay đổi, nó sẽ là XDocument chứ không phải XmlDocument. –

+0

Ngoài ra, câu trả lời cho câu hỏi này có dành riêng cho C# không? –

+2

AFAIK, 'dynamic' là một tính năng của C#, do đó, vâng, cụ thể cho C#. – svick

Trả lời

6

Đưa ra một số nhận xét, hãy để tôi cung cấp câu trả lời thay thế. Câu hỏi ban đầu được hỏi tại sao XmlDocument không động trong .NET 4. Trong khi nó có thể thêm khả năng đặc tính "expando" vào các lớp tài liệu xml hiện có thông qua IDynamicMetaObjectProvider, làm như vậy có thể là một nỗ lực không tầm thường. Làm cho mô hình đối tượng Xml ban đầu từ System.Xml hoàn toàn năng động sẽ yêu cầu một số sửa đổi mở rộng của khuôn khổ Xml và sẽ yêu cầu IDynamicMetaObjectProvider đó được thêm vào mọi đối tượng có liên quan. Điều đó bao gồm XmlDocument, XmlElement, XmlAttribute, XmlNode và tất cả các loại nội dung xml khác như nhận xét, nút văn bản, v.v. Ngoài ra, một số lượng đáng kể cơ sở hạ tầng hỗ trợ, loại nội bộ, v.v ... có liên quan đến việc tra cứu và xử lý các phần tử và thuộc tính và giá trị cũng sẽ cần phải được sửa đổi (mở Reflector, và xem System.Xml ... hơn một nửa các kiểu là nội bộ, và chúng tất cả đều phụ thuộc lẫn nhau với nhau và các kiểu công khai có sẵn .)

Điều quan trọng là phải xem xét phạm vi thích hợp của việc triển khai thuộc tính expando cho Xml trong .NET. Bạn sẽ dừng lại ở chỉ các XmlDocument và các loại liên quan? Hoặc sẽ thích hợp hơn để bao gồm XPath, Lược đồ Xml, v.v ...?

Để trả lời câu hỏi gốc, "Tại sao không phải là XmlDocument động trong .NET 4?", Tôi nghĩ câu trả lời đơn giản là: Triển khai API đầy đủ 'động' hoặc trong trường hợp Xml tại đây, API cung cấp mở rộng tài sản của các tài liệu xml tùy ý, là một nhiệm vụ tầm thường. Với đạo đức làm việc của Microsoft, nó có ý nghĩa hợp lý rằng họ sẽ không tiếp cận một nhiệm vụ như vậy một cách nhẹ nhàng, và nếu họ cố gắng thực hiện các thuộc tính mở rộng cho khung công tác Xml, tôi hy vọng nó sẽ được thực hiện với cùng mức độ chú ý và chăm sóc cẩn thận họ cung cấp cho phần còn lại của .NET.

+1

Câu trả lời thú vị, nhưng câu hỏi của tôi là, tại sao không có bất kỳ loại nào có thể xử lý cú pháp 'xmlDoc.root.subnode.subsubnode' trong C#? (Có lẽ bằng cách thực hiện 'IDynamicMetaObjectProvider', nếu tôi hiểu nó chính xác.) – svick

+0

Nhưng bạn có thể làm điều đó trong C# 4, bạn có thể tự mình quản lý tra cứu thành viên, xem ví dụ: http://channel9.msdn.com/posts/RobBagby/deCast-Dynamic-Xml-with-C-40/. – svick

+0

Có, các đối tượng có thể thực sự năng động. Xem các lớp 'DynamicObject' và' ExpandoObject' trên MSDN và các giao diện mà chúng triển khai. Do đó, câu trả lời có hiệu quả không chính xác và có thể thực hiện được, ví dụ: 'XmlDocument' để thêm khả năng được truy cập dưới dạng gốc ((động)) .foo.bar.baz' trong các bản phát hành sau này. –

-1

Có lẽ họ không nghĩ về điều đó, và, các lập trình viên thường không kích hoạt hạnh phúc với việc đưa động lực lên khắp nơi: năng động là một quả bom thời gian. Nắm bắt nhiều nhất có thể vào thời gian biên dịch ...

+1

Vấn đề là, bạn không bao giờ biết XML nào bạn sẽ nhận được và liệu đó có phải là điều bạn mong đợi hay không. Và nếu không, bạn phải xử lý nó trong thời gian chạy, cho dù bạn sử dụng dynymics hay không. – svick

+0

@svick: đó là việc xác thực lược đồ là gì. –

-2

Vì XmlDocument đặt trước hệ gen và sửa nó sẽ phá vỡ mã cũ.

Ngoài ra, XmlDocument được liệt kê là đã lỗi thời.

+3

Làm cách nào để ngắt mã hiện tại nếu một lớp đã hỗ trợ giao diện mới không có ở đó khi mã được viết? – Niki

12

Tôi ngạc nhiên trước số lượng thảo luận có vẻ có thẩm quyền mà không có câu trả lời. Câu hỏi của bạn là FANTASTIC. Nó giải quyết chính xác những điều tuyệt vời mà từ khóa dynamic được dự định. Vấn đề là, không nhiều người thực sự biết cách sử dụng nó một cách đầy đủ nhất.

Trong khi MS không xây dựng các đối tượng XML động cho chúng tôi, chúng đã cung cấp cho chúng tôi các công cụ để tự làm với lớp DynamicObject. Đây là một cách để làm những gì bạn đang yêu cầu với lớp học cũ 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; 
    } 
} 

Và đây là cách bạn sẽ gọi mã.Lưu ý rằng điều này chỉ biên dịch trong 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); 
     } 
    } 
} 

Tôi không thể nhận tất cả tín dụng cho việc này. Bamboo wrote this code cho Boo trở lại vào năm 2003. C# đã dần dần nhận được các tính năng mà Boo đã có trong .NET trong nhiều năm ... suy luận kiểu đầu tiên, và bây giờ là phong cách IQuackFu DynamicObject. Khi họ triển khai macro ngôn ngữ để bạn có thể tạo DSL, tôi nghĩ họ sẽ bắt kịp.

Tôi sẽ để lại văn bản kiểu phiên bản XElement mới hơn của mã này cho người đọc.

+1

"Nó giải quyết CHÍNH XÁC từ khóa động được dành cho" - từ khóa 'dynamic' là gì _intended_ cho là cái gì đó chỉ là các nhà thiết kế của ngôn ngữ, và liên quan một phần của thư viện thời gian chạy, có thể trả lời tác giả. Trong trường hợp này, nó được lặp đi lặp lại cho biết rằng trường hợp sử dụng # 1 cho 'dynamic' thực sự làm việc với các API Office và # 2 đang làm việc với các đối tượng được tiếp xúc với các ngôn ngữ động. Đây không phải là để nói rằng không có sử dụng hợp lệ khác, nhưng tôi nghĩ rằng tuyên bố "dành cho" là một chút quá quyết đoán. –

+1

Đủ công bằng. Tôi cho rằng tôi nên nói "Nó giải quyết những gì lớp DynamicObject kết hợp với từ khóa động là MOST LIKELY dành cho". Ngay cả những blogger trên Microsoft đang sử dụng nó cho mục đích này: http://blogs.msdn.com/b/csharpfaq/archive/2009/10/19/dynamic-in-c-4-0-creating- wrappers-with-dynamicobject.aspx – mattmc3

Các vấn đề liên quan