/// <summary> /// Gets an ObjectInfo instance by the attributes of the specified XmlNode. /// </summary> /// <param name="node"></param> /// <returns></returns> private ObjectInfo GetObjectInfo(XmlNode node) { ObjectInfo 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 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 = null; // 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; byte[] barr = null; if (!String.IsNullOrEmpty(info.Value)) { barr = System.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.ConvertFrom(info.Value); return obj; } } catch { ; } obj = Activator.CreateInstance(type); if (obj == null) throw new Exception("Instance could not be created."); return obj; } catch (Exception e) { string msg = "Creation of an instance failed. Type: " + info.Type + " Assembly: " + info.Assembly + " Cause: " + e.Message; if (IgnoreCreationErrors) { return null; } else throw new Exception(msg, e); } }
/// <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) { Contract.Requires(0 <= info.Type.Length - 2); Contract.Requires(length >= 0); // 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; }
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 = null; // 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; byte[] barr = null; if (!String.IsNullOrEmpty(info.Value)) { barr = System.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.ConvertFrom(info.Value); return(obj); } } catch {; } obj = Activator.CreateInstance(type); if (obj == null) { throw new Exception("Instance could not be created."); } return(obj); } catch (Exception e) { string msg = "Creation of an instance failed. Type: " + info.Type + " Assembly: " + info.Assembly + " Cause: " + e.Message; if (IgnoreCreationErrors) { return(null); } else { throw new Exception(msg, e); } } }
/// <summary> /// Reads the properties of the specified node and sets them an the parent object. /// </summary> /// <param name="parent"></param> /// <param name="node"></param> /// <remarks> /// This is the central method which is called recursivly! /// </remarks> protected object GetProperties(object parent, XmlNode node) { if (parent == null) { return(parent); } // Get the properties XmlNodeList nl = node.SelectNodes(taglib.PROPERTIES_TAG + "/" + taglib.PROPERTY_TAG); // Properties found? if (nl == null || nl.Count == 0) { // No properties found... perhaps a collection? if (TypeInfo.IsCollection(parent.GetType())) { SetCollectionValues((ICollection)parent, node); } else { // Nothing to do here return(parent); } } // Loop the properties found foreach (XmlNode prop in nl) { // Collect the nodes type information about the property to deserialize ObjectInfo oi = GetObjectInfo(prop); // Enough info? if (oi.IsSufficient && !String.IsNullOrEmpty(oi.Name)) { object obj = null; // Create an instance, but note: arrays always need the size for instantiation if (TypeInfo.IsArray(oi.Type)) { int c = GetArrayLength(prop); obj = CreateArrayInstance(oi, c); } else { obj = CreateInstance(oi); } // Process the property's properties (recursive call of this method) if (obj != null) { obj = GetProperties(obj, prop); } // Setting the instance (or null) as the property's value PropertyInfo pi = parent.GetType().GetProperty(oi.Name); if (obj != null && pi != null) { pi.SetValue(parent, obj, null); } } } var identifyible = parent as IEntity; if (identifyible != null) { var list = GetIdentifyibleTypeList(identifyible.GetType()); if (!list.ContainsKey(identifyible.Id)) { list.Add(identifyible.Id, identifyible); return(list[identifyible.Id]); } return(list[identifyible.Id]); } return(parent); }