OK, OK, I do sound like a fanboy - but I just seriously simplified many chunks of code in my yet-unannounced P2P product simply by using a XPathNavigator. This class has been present in the .NET BCL since the very beginning and I've been aware of it's existence for quite some time - Aaron Skonnard's MSDN Magazine article describes it in a lot of detail. The article is from September 2001 (!) but is still mainly valid - as is the code does not compile with the current .NET Framework version (2.0) but that's due to a few breaking changes in the API that are easy to fix.
For those that do not want/need to read the entire article, XPathNavigator is an abstract accessor into some model (object hierarchy of any kind) that is pluggable into the .NET XPath navigation system so that you can treat your model as an XML document and evaluate XPath expressions against it. Even though XPath expressions can get very ugly and complicated, XPathNavigator exposes very simple API in the shape of methods like MoveToFirstChild (move to the first child node of the current context node), MoveToNextAttribute (move to the next attribute of the current context node), Name (property returns name of the current context node) etc. All in all, there are about 20 methods/properties to override but most of them are really easy to implement.
What do you get with this? Well, imagine a quite reasonable scenario - you are getting the data from an external source (your app does not produce it). You map it to a model where you have a hierarchical relationship with many Objects because elements of this hierarchy can be from various different classes (String, Int64, Dictionary) - otherwise you'd just use a generic collection. Now the problem - how do you validate the structure? More concretely, what if you want to make sure that the shape of this model is such that the root is an Int64, with two String child nodes of which the second one has one Dictionary child? Even worse, what if there are several (still fixed number) variations of this structure that are possible?
Standard approach would be just to walk the hierarchy, ask for the type at each step (so a lot of if (abc) is Type) then cast (two kinds, with as operator for reference types and for value types a C-style cast), then continue traversal. This gets very ugly very fast and clutters your code immensely. Getting to a particular node requires same kind of detect type-cast-continue traversal dance. I won't even mention how the code that extracts a non-trivial sub-hierarchy looks like - for example, what if you want all child nodes of a particular node (whose property is equal to some value), but only nodes whose preceding siblings have a property with a value less than some fixed constant? Good luck writing and maintaining a function that will do this - if the expression for this sub-hierarchy changes if just a bit, you have to go through the code and fix it on a right place.
All these problems are solved with XPathNavigator. First of all, you get export to XML for free - just match a document node and then traverse the hierarchy spitting out the OuterXml property of each and every node. Thus, you can validate the document with the XML Schema. If you need to extract sub-hierarchies that's exactly what XPath was made for. Finally, if you have more complex extraction scenarios you can use XSLT to extract the information you need. This thing just gets better and better.
That said, your model still needs to be relatively simple in order to be treated like XML. If that is not the case, do not try to force-fit it - you will pay more in having to work around the code you built to simplify things.
A few tips for XPathNavigator implementers:
- read MSDN Magazine article thoroughly and study the code that comes with it
- don't forget that the article is 4 years old and some things don't apply any more
- MoveToParent will NOT be called after MoveToNextAttribute returns false (this looked intuitive to me but is not the case)
- it is absolutely crucial that navigator's Clone method implementation really clones all the state in your navigator (at least one of the examples in the article does not do that) - Clone helps the XPath internal implementation to backtrack
Be the first to rate this post
- Currently 0/5 Stars.
- 1
- 2
- 3
- 4
- 5