Implementing an XML Data Provider for Oxite, Part III
In my previous post, I detailed the outline of how I would implement the XML Data Provider for Oxite.
After some refactoring and additional coding, the class structure looks like this:
The XmlTableBase and XmlTable classes are re-usable for generic LINQ friendly XML table-like storage of classes.
Most of the “tables” in the OxiteXmlContext use the XmlTable class directly. Most classes which inherit from the NamedEntity base class in Oxite get handled by the OxiteEntityTable class, which adds default behavior on top of the XmlTable. Those classes which require additional logic when serializing / deserializing the entities are implemented as classes which inherit either from XmlTable or OxiteEntityTable, as shown in the class diagram above.
I have opted to not use the standard XML serialization classes for this, because I wanted to reuse the existing classes in the Oxite model, which aren’t decorated with any serialization attributes. This allows for the Oxite model to change somewhat without any maintenance being required for the XML Data Provider.
The other option had been to implement a layer on top of the Oxite model which has Xml serialization attributes, and although perhaps a better practice, it just seemed too redundant at this point.
Therefore I have written custom serialization and deserialization methods that use generics and reflection to achieve storage and retrieval.
The serialization/deserialization methods recognize all the standard value type codes in .NET, as well as Enums, Nullable<T>, Guid and the Uri types.
Basically, the deserialization process iterates all attributes and child elements of the entity element and invokes this method:
private static void SetPropertyValue(object obj,
string propertyName, object value)
{
if (obj == null || value == null)
return;
PropertyInfo propertyInfo = obj.GetType().GetProperty(
propertyName, BINDING_FLAGS);
// Skip non-existing properties. Will be handled with
// custom deserialization by descendant classes
if (propertyInfo == null)
return;
Type propertyType = propertyInfo.PropertyType;
// If nullable generic type, use the generic
// parameter instead
if (propertyType.Name == "Nullable`1")
propertyType = propertyType.GetGenericArguments()[0];
if (Type.GetTypeCode(propertyType) == TypeCode.Object)
{
if (propertyType == typeof(Guid))
value = new Guid(value.ToString());
else if (propertyType == typeof(Uri))
value = new Uri(value.ToString());
else // Skip on unknown types
return;
}
if (propertyType.IsEnum)
value = Enum.Parse(propertyType, value.ToString());
propertyInfo.SetValue(obj, Convert.ChangeType(value,
propertyType, CultureInfo.InvariantCulture), null);
}
Most of the XML Data Provider is now complete. I opted for simplicity over completeness for the initial version, deferring caching in favor of a more straight-forward thread-safety mechanism which locks the class on operations that modify files. Currently this has the weakness of locking all file operations of the same type, regardless if they conflict or not. Two comments being saved at the same time for separate posts will be queued, despite them being saved to separate files.
At the moment I feel it’s more important to work out the kinks in the repository implementations and get to a point where everything works, before I polish the whole thing to a fancy shine.

