XmlObject - Adaptive Object Model |
Better Designs Faster |
XmlObject Base Class |
The XmlObject base class library is actually three abstract classes (and an interface) that are in turn derived from System classes. Each of the classes is named after the class it is derived from, but of course each lives in a different namespace. In the diagram below System classes are shown with the names in gray and my derived classes are shown with the names in black. The derived XmlDocument class constructor requires that one supply an object that implements the IXmlObjectResolver interface. Resolvers are discussed down the road a bit, but in general they are how the framework locates the Type definitions from which object instances are constructed. Objects that implement this interface are required to have a single method, GetType. The signatures for GetType looks like this. Type GetType( string prefix, string localName, string namespaceURI );
The GetType method takes three strings as parameters. The first is the namespace prefix, the second is a localName of an XML element, and the third is a namespaceURI. However where the XML parser sees these as data, the XmlObject framework sees them as metadata. Notice how the signature of this method matches that of the CreateElement and CreateAttribute methods defined in the System.Xml.XmlDocument base class. XmlAttribute CreateAttribute( string prefix, string localName, string namespaceURI )
XmlElement CreateElement( string prefix, string localName, string namespaceURI )
The GetType method will need to use this metadata to locate and return an appropriate Type object. This Type object is then used by the XmlObject Framework to resolve and then instantiate desired Types finally creating XmlElement and XmlAttribute objects. I encourage you to step through the implementations of CreateAttribute and CreateElement in the samples for an example. A very simple implementation of IXmlObjectResolver might hardcode the relationship between (prefix, localName, & namespaceURI) and Type object. A more sophisticated mechanism might use reflection to resolve these relationships, The provided source has two such examples. In addition to the overrides of CreateElement and CreateAttribute, the derived XmlDocument class hides a number of base class methods. This is done so that the derived class implementations can return derived XmlAttribute, XmlElement, and XmlElementList objects. Otherwise these methods function identically to their base class implementations. Also, In many cases you will notice that the derived implementation simply delegates a call to the base class implementation. This is done mostly as a debug aid, trusting that the optimizer will recognize and clean up such obvious inefficiencies in release builds. While not strictly necessary, the derived XmlElement and XmlAttribute classes exist so that derived implementations of CreateElement and CreateAttribute can pass derived XmlDocument types during construction, thus avoiding an ugly up cast. |