DynamicXml-XML for dynamic read Operations (a general implementation from XML to Object)

Source: Internet
Author: User

A recent project used a lot of XML files with different structures. So I searched some articles on the Internet and wrote my own code based on actual problems.

Since we have obtained this knowledge, we do not dare to take it alone and share it. This is not very mature. I hope you can improve it together, provide valuable comments, and make progress together.

Target
Based on existing XML files, such:

<Root> <books> <book> <author> John Savacki </author> <title> E. g. title </title> <price> 20.50 </price> </book> <author> Tom Curly </author> <title> E. g. title 2 </title> <price> 26.50 </price> </book> </books> </root> or an XML file similar to any structure can be initialized.
Dynamic dx = new DynamicXml (xml );
And read the property value:

Dx. books. book [0]. author, dx. books. book [2]. price

Solution
Naturally, DynamicObject introduced in C #4.0 is selected. The key is that this function cannot be provided in the existing. net Framework.

In this case, the subclass is inherited from this class, And IEnumerable is also required.

A little introduction:

The DynamicObject class allows you to define which operations can be performed on dynamic objects and how to perform these operations.
If you only need to set and retrieve attributes, you can only overwrite the TrySetMember and TryGetMember methods.

 

IEnumerable public enumerator, which supports simple iteration on non-generic sets.
We should all know that IEnumerable is required to implement a custom set.

Public IEnumerator GetEnumerator ()

That is to say, at least three functions need to be completed to meet the requirements:

TrySetMember, TryGetMember, GetEnumerator

 

Implementation
Through the above analysis, we know that this class should look like this:

Public class DynamicXml: DynamicObject, IEnumerable
{

Public DynamicXml (string text)
{
}

Public override bool TryGetMember (GetMemberBinder binder, out object result)
{
}

Public override bool TryGetIndex (GetIndexBinder binder, object [] indexes, out object result)
{
}

Public IEnumerator GetEnumerator ()
{
}
}

 

In the constructor, we want to read the XML content and load the values of all elements.

In TrySetMember, we provide an implementation for the operation of setting Member values to specify Dynamic Behavior for setting attribute values. In this article, we only consider reading XML content, so we do not need to rewrite this function.

In TryGetMember, we need to provide implementation for the operation to get the member value.

In TryGetIndex, we need to provide the implementation for the operation of getting values by index.

 

The implementation code is as follows:

 

Public class DynamicXml: DynamicObject, IEnumerable {private readonly List <XElement> _ elements; public DynamicXml (string text) {var doc = XDocument. parse (text); _ elements = new List <XElement> {doc. root };} protected DynamicXml (XElement element) {_ elements = new List <XElement >{element };} protected DynamicXml (IEnumerable <XElement> elements) {_ elements = new List <XElement> (elements);} publi C override bool TryGetMember (GetMemberBinder binder, out object result) {result = null; if (binder. name = "Value") result = _ elements [0]. value; else if (binder. name = "Count") result = _ elements. count; else {var attr = _ elements [0]. attribute (XName. get (binder. name); if (attr! = Null) result = attr; else {var items = _ elements. descendants (XName. get (binder. name); if (items = null | items. count () = 0) return false; result = new DynamicXml (items) ;}} return true;} public override bool TryGetIndex (GetIndexBinder binder, object [] indexes, out object result) {int ndx = (int) indexes [0]; result = new DynamicXml (_ elements [ndx]); return true;} public IEnumerator GetEnumerator () {foreach (var element in _ elements) yield return new DynamicXml (element) ;}} use
In specific use, some of them are very interesting. Because dynamic is available, you can use the same variable to obtain XML files of different structures. The Code is as follows:

 

Static void Main (string [] args) {string xml = @ "<root> <books> <book> <author> John Savacki </author> <title> E. g. title </title> <price> 20.50 </price> </book> <author> Tom Curly </author> <title> E. g. title 2 </title> <price> 26.50 </price> </book> </books> </root> "; dynamic dx = new DynamicXml (xml); Console. writeLine ("----- Book List -----"); foreach (dynamic B in dx. books. book) {Console. writeLine ("author = '{0}'", B. author. value); print (B);} Console. writeLine ("------ Book List End ------"); string xml2 = @ "<root> <products> <product> <title> iPhone 4 </title> <price> 2222.50 </price> <quantity> 10 </quantity> </product> <title> Lenovo IdeaPad </title> <price> 5432.50 </price> <quantity> 15 </quantity> </product> </products> </root> "; dx = new DynamicXml (xml2); Console. writeLine ("----- Product List -----"); foreach (dynamic B in dx. products. product) {Console. writeLine ("quantity = '{0}'", B. quantity. value); print (B);} Console. writeLine ("------ Product List End ------"); Console. read ();}
I took out the print function, so I would like to figure it out. Because the two XML structures are similar, the following functions can be used at the same time. -- of course, we can also define an interface for this situation.
 
Static void print (dynamic B) {Console. writeLine ("Title = '{0}'", B. title. value); Console. writeLine ("price = '{0}'", B. price. value);} is not a very profound thing, but it is expected to save some time for friends who have the same problems.

If you can better master Dynamic, you can save some reflection code, but this is another topic.

From ASP. NET (Alex Song) of joy)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.