This struct records relevant object information.
/// <summary> /// Sets the property attributes of a Property to an XmlNode. /// </summary> /// <param name="propertyName"></param> /// <param name="type"></param> /// <param name="node"></param> private void SetObjectInfoAttributes(String propertyName, Type type, XmlNode node) { var objinfo = new ObjectInfo(); GetObjectInfo(propertyName, type); if (type != null) { objinfo = GetObjectInfo(propertyName, type); } // Use of a TypeDictionary? if (usetypedictionary) { // TypeDictionary String typekey = GetTypeKey(type); XmlAttribute att = node.OwnerDocument.CreateAttribute(taglib.NAME_TAG); att.Value = objinfo.Name; node.Attributes.Append(att); att = node.OwnerDocument.CreateAttribute(taglib.TYPE_TAG); att.Value = typekey; node.Attributes.Append(att); // The assembly will be set, also, but it's always empty. att = node.OwnerDocument.CreateAttribute(taglib.ASSEMBLY_TAG); att.Value = ""; node.Attributes.Append(att); } else { // No TypeDictionary XmlAttribute att = node.OwnerDocument.CreateAttribute(taglib.NAME_TAG); att.Value = objinfo.Name; node.Attributes.Append(att); att = node.OwnerDocument.CreateAttribute(taglib.TYPE_TAG); att.Value = objinfo.Type; node.Attributes.Append(att); att = node.OwnerDocument.CreateAttribute(taglib.ASSEMBLY_TAG); att.Value = objinfo.Assembly; node.Attributes.Append(att); } }
/// <summary> /// Creates an instance by the specified ObjectInfo. /// </summary> /// <param name="info"></param> /// <returns></returns> private object CreateInstance(ObjectInfo info) { try { // Enough information to create an instance? if (!info.IsSufficient) return null; object obj; // Get the Type Type type = CreateType(info.Assembly, info.Type); if (type == null) { throw new Exception("Assembly or Type not found."); } // Ok, we've got the Type, now try to create an instance. // Is there a binary constructor? if(!String.IsNullOrEmpty(info.ConstructorParamType)) { Object ctorparam = null; if (!String.IsNullOrEmpty(info.Value)) { byte[] barr = Convert.FromBase64String(info.Value); Type ctorparamtype = CreateType(info.ConstructorParamAssembly, info.ConstructorParamType); // What type of parameter is needed? if(typeof(Stream).IsAssignableFrom(ctorparamtype)) { // Stream ctorparam = new MemoryStream(barr); } else if (typeof(byte[]).IsAssignableFrom(ctorparamtype)) { // byte[] ctorparam = barr; } } obj = Activator.CreateInstance(type, new object[] { ctorparam }); return obj; } // Until now only properties with binary data support constructors with parameters // Problem: only parameterless constructors or constructors with one parameter // which can be converted from String are supported. // Failure Example: // string s = new string(); // string s = new string(""); // This cannot be compiled, but the follwing works; // string s = new string("".ToCharArray()); // The TypeConverter provides a way to instantite objects by non-parameterless // constructors if they can be converted fro String try { TypeConverter tc = GetConverter(type); if (tc.CanConvertFrom(typeof(string))) { obj = tc.ConvertFromInvariantString(info.Value); return obj; } } catch { ; } return Activator.CreateInstance(type); } catch (Exception e) { string msg = "Creation of an instance failed. Type: " + info.Type + " Assembly: " + info.Assembly + " Cause: " + e.Message; if (IgnoreCreationErrors) { return null; } throw new Exception(msg, e); } }
/// <summary> /// Gets an ObjectInfo instance by the attributes of the specified XmlNode. /// </summary> /// <param name="node"></param> /// <returns></returns> private ObjectInfo GetObjectInfo(XmlNode node) { var oi = new ObjectInfo(); String typekey = GetAttributeValue(node, taglib.TYPE_TAG); TypeInfo ti = TranslateTypeByKey(typekey); if (ti != null) { oi.Type = ti.TypeName; oi.Assembly = ti.AssemblyName; } // If a TypeDictionary is given, did we find the necessary information to create an instance? // If not, try to get information by the Node itself if (!oi.IsSufficient) { oi.Type = GetAttributeValue(node, taglib.TYPE_TAG); oi.Assembly = GetAttributeValue(node, taglib.ASSEMBLY_TAG); } // Name and Value oi.Name = GetAttributeValue(node, taglib.NAME_TAG); oi.Value = node.InnerText; // Binary Constructor ti = GetBinaryConstructorType(node); if (ti != null) { // Binary constructor info given oi.ConstructorParamType = ti.TypeName; oi.ConstructorParamAssembly = ti.AssemblyName; // Make sure to read the value from the binary data Node (setting oi.Value = node.InnerText as above is a bit dirty) XmlNode datanode = node.SelectSingleNode(taglib.BINARY_DATA_TAG); if (datanode != null) { oi.Value = datanode.InnerText; } else { datanode = node.SelectSingleNode(taglib.CONSTRUCTOR_TAG); if (datanode != null) { datanode = datanode.SelectSingleNode(taglib.BINARY_DATA_TAG); if (datanode != null) { oi.Value = datanode.InnerText; } } } } return oi; }
/// <summary> /// Creates an instance of an Array by the specified ObjectInfo. /// </summary> /// <param name="info"></param> /// <param name="length"></param> /// <returns></returns> private Array CreateArrayInstance(ObjectInfo info, int length) { // The Type name of an array ends with "[]" // Exclude this to get the real Type string typename = info.Type.Substring(0, info.Type.Length - 2); Type t = CreateType(info.Assembly, typename); Array arr = Array.CreateInstance(t, length); return arr; }