One extra feature I added to the XmlProvider class was the ability to remove document creation and management from the serialization process. It made sense to me that the developer will know what Xml Nodes need to be serialized in what way. Thus the class returns an XmlNode object rather than create a whole Xml file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | using System; using System.Xml; using System.Reflection; using System.Collections.Generic; namespace FocusedGames.Xml { public class XmlProvider { #region Serialization public XmlNode Serialize(object obj, XmlDocument doc){ } #endregion } } |
Before we move on to the creation of the Serialize function, we need some helper methods. The first two are essentially the same function, but operate on two different object types. The goal with the method is to grab a specific attribute from either an object definition itself or a property inside an object.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | private static T GetAttribute<T>(object obj) where T : class{ Type objectType = obj.GetType(); object[] objectAttributes = objectType.GetCustomAttributes(true); for (int i = 0; i < objectAttributes.Length; i++) { if (objectAttributes[i].GetType() == typeof(T)) return objectAttributes[i] as T; } return default(T); } private static T GetAttribute<T>(PropertyInfo info) where T : class{ object[] objectAttributes = info.GetCustomAttributes(true); for (int i = 0; i < objectAttributes.Length; i++) { if (objectAttributes[i].GetType() == typeof(T)) return objectAttributes[i] as T; } return default(T); } |
The next method was built because I was having some problems with finding types with the built-in TypeBuilder. Note that unfortunately it will not work to the full extent on the Zune and Xbox 360, but we will solve that issue when it arises. The problem stems from the way I store the type information in the Xml.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | public static Type GetType(string typeName) { #if ZUNE || XBOX return Type.GetType(typeName); #else if (String.IsNullOrEmpty(typeName)) throw new ArgumentException("Provided type name was invalid."); // Get a list of assemblies first... Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); // Loop through until we find the type. foreach (Assembly assembly in assemblies) { Type t = assembly.GetType(typeName); if (t == null) { Type[] ts = assembly.GetTypes(); foreach (Type type in ts) if (type.Name == typeName || type.AssemblyQualifiedName == typeName) return type; } if (t != null) return t; } // We may need to fall back on the built in builder. return System.Reflection.Emit.TypeBuilder.GetType(typeName); #endif } |
Ok, now we are ready to actually serialize some data!