Introduction
Please refer to the below links before reading this article. It gives an idea of how to use TryGetMember
method of DynamicObject
class which is necessary to understand this article because we used it in our example for XmlNavigation
.
Now, manipulating XElements
can be done with methods of XElement
objects and the syntax may be:
XElement xmlNavigation = XElement.Parse(@"
<Emails>
<Email>
<Id>1</Id>
<Description>sanjay.patolia@gmail.com</Description>
</Email>
<Email>
<Id>2</Id>
<Description>sanjay.patolia@patni.com</Description>
</Email>
</Emails>
");
var email = xmlNavigation.Elements("Email");
In the above example, to fetch all the "Email
" elements, we used Elements("Emails")
statement. In the same way, we use other methods too to manipulate other XML reading oprations. Here, though our work has been done for fetching elements, it does not come into easily readable format. We can achieve that kind of functionality using DynamicObject
class and a dynamic
keyword, which allows us to navigate through XML in easily readable format. We just need to keep track of XmlStructure
.
Let's talk a bit about DynamicObject
class.
DynamicObject
class allows us to implement operations dynamically, when we try to get member values or set member values. Please refer to the above link for more information on DynamicObject.TryGetMember
method. Here, we will look at TryGetMember
method of DynamicObject
class, which will be called when we will try to get values of properties which are not implemented in the class.
Let us see an example of XML Navigation using DynamincObject
class and a dynamic
keyword.
namespace XmlNavigationUsingDynamic
{
class Program
{
static void Main(string[] args)
{
dynamic xmlNavigation = new XmlNavigationUsingDynamic
(XElement.Parse(@"
<Emails>
<Email>
<Id>1</Id>
<Description>sanjay.patolia@gmail.com</Description>
</Email>
<Email>
<Id>2</Id>
<Description>sanjay.patolia@patni.com</Description>
</Email>
</Emails>
"));
IEnumerable<XElement> descriptionNodes = xmlNavigation.Email.Description;
descriptionNodes.ToList().ForEach(emailDesc =>
{
Console.WriteLine(emailDesc);
});
Console.ReadKey(true);
}
}
public class XmlNavigationUsingDynamic : DynamicObject, IEnumerable<XElement>
{
IEnumerable<XElement> node = null;
public XmlNavigationUsingDynamic(params XElement[] nodes)
{
node = nodes;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
var genericNode = node.Elements(binder.Name).ToArray();
result = new XmlNavigationUsingDynamic(genericNode);
return true;
}
public IEnumerator<XElement> GetEnumerator()
{
return node.GetEnumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}
In the above example:
-
dynamic xmlNavigation = new XmlNavigationUsingDynamic
(XElement.Parse(@"
<Emails>
<Email>
<Id>1</Id>
<Description>sanjay.patolia@gmail.com</Description>
</Email>
<Email>
<Id>2</Id>
<Description>sanjay.patolia@patni.com</Description>
</Email>
</Emails>
"));
creates an XML file in memory.
-
xmlNavigation.Email
xmlNavigation
is an object of XmlNavigationUsingDynamic
class and .Email
is a member (considering a member) of that class. So it is trying to access that member of that class. This statement will call the TryGetMember
method, it performs an operation and sets result
object which will be the base of "Description
", because the result
object is set to an object of XmlNavigationUsingDynamic
class.
-
xmlNavigation.Email.Description
Description will be called from result
(object set from TryGetMember
method) and returns IEnumerable<XElement>
because we have implemented IEnumerable<XElement>
and node.GetEnumerator()
method is called which is implemented from IEnumerable
interface and returns IEnumerable<XElement>
so at last we are iterating it to get element "Description
".
So, look at the difference in traversing the XML file:
var email = xmlNavigation.Elements("Email");
IEnumerable<XElement> descriptionNodes = xmlNavigation.Email.Description;
Thus, in this way we can perform other XML navigation operations too.
History
- 19th April, 2011: Initial post