/** Reads a list of dataobjects from this nodes child of given name, returns null if not found. Can be referenced, or full. */ protected List <T> ReadNamedDataObjectList <T>(XElement node, string name, FieldReferenceType referenceType, DataLibrary <T> library = null) where T : NamedDataObject { node = node.Element(name); if (node == null) { return(null); } var list = new List <T>(); string subNodeName = GetClassAttributesForType(typeof(T)).NodeName; library = library ?? NamedDataObject.GetLibraryForType <T>(); if (library == null && referenceType != FieldReferenceType.Full) { throw new Exception("Can not load type " + typeof(T) + " as no default library is defined, and it is stored referenced."); } foreach (var subNode in node.Elements(subNodeName)) { T item = null; switch (referenceType) { case FieldReferenceType.Full: item = (T)Activator.CreateInstance(typeof(T)); item.ReadNode(subNode); break; case FieldReferenceType.ID: var fieldId = int.Parse(subNode.Value); item = (T)library._byID(fieldId); break; case FieldReferenceType.Name: var fieldName = subNode.Value; item = (T)library._byName(fieldName); break; } list.Add(item); } return(list); }
/** * Writes a value to the writer. * Object can be primative, string, or DataObject, or enum * Or an array or list of either primative, string or DataObject. * * If name is null or empty value will be written to node directly. * * If byReference is true any NamedDataObjects will be referenced by name instead of writing them out in full. */ protected void WriteValue(XElement node, string name, object value, FieldReferenceType referenceType = FieldReferenceType.Full) { if (value == null) { return; } if (string.IsNullOrEmpty(name)) { WriteDirect(node, value, referenceType); return; } var subNode = new XElement(name); WriteDirect(subNode, value, referenceType); node.Add(subNode); }
/** New display extended field attributes. Use null string for default fieldname */ public FieldAttrAttribute(string displayName, FieldReferenceType referenceType = FieldReferenceType.Full, bool ignore = false) { DisplayName = displayName; Ignore = ignore; ReferenceType = referenceType; }
/** * Writes a value direct to a node. */ protected void WriteDirect(XElement node, object value, FieldReferenceType referenceType = FieldReferenceType.Full) { if (value == null) { return; } // Todo: use stringbuilder for performance. var valueType = value.GetType(); // ----------------------------------------- // single items if (valueType.IsPrimitive || (value is string)) { node.Value = value.ToString(); return; } if (value is DateTime) { node.Value = ((DateTime)value).ToString("u"); return; } // use custom dataobject serialization if (value is DataObject) { if (value is NamedDataObject) { switch (referenceType) { case FieldReferenceType.Name: node.Value = (value as NamedDataObject).Name; return; case FieldReferenceType.ID: node.Value = (value as NamedDataObject).ID.ToString(); return; } } (value as DataObject).WriteNode(node); return; } if (valueType.IsEnum) { node.Value = (value as Enum).ToString(); return; } // check for ReadWriteable interface if (value is iSerializable) { (value as iSerializable).WriteNode(node); return; } // ----------------------------------------- // arrays and lists // simple arrays if (valueType.IsArray && valueType.HasElementType && (valueType.GetElementType().IsPrimitive || valueType.GetElementType() == typeof(string))) { var array = (Array)value; var sb = new StringBuilder(); foreach (var element in array) { sb.Append(element + ","); } if (sb.Length >= 1) { sb.Remove(sb.Length - 1, 1); } node.Value = sb.ToString(); return; } // array or list of data objects if (value is IList) { var list = (IList)(value); if (list.Count == 0) { return; } Type entryType = null; if (valueType.GetGenericArguments().Length >= 1) { entryType = valueType.GetGenericArguments()[0]; } // If we know the generic type use this, otherwise just check each entry. // Knowing the generic type allows nulls to be written with the correct type. if (entryType != null) { var classAttr = DataObject.GetClassAttributesForType(entryType); var nodeName = classAttr.NodeName; foreach (object entry in list) { WriteValue(node, nodeName, entry, referenceType); } } else { foreach (object entry in list) { var classAttr = DataObject.GetClassAttributesForType(entry.GetType()); var nodeName = classAttr.NodeName; WriteValue(node, nodeName, entry, referenceType); } } return; } // ----------------------------------------- // some random types if (value is BitArray) { string stringValue = ""; foreach (bool bit in (value as BitArray)) { stringValue += bit ? "1" : "0"; } node.Value = stringValue; return; } if (value is Dictionary <string, string> ) { foreach (KeyValuePair <string, string> entry in (value as Dictionary <String, String>)) { node.Add(new XElement("entry", entry.Key + ": " + entry.Value)); } return; } if (value is Dictionary <string, int> ) { foreach (KeyValuePair <string, int> entry in (value as Dictionary <String, int>)) { node.Add(new XElement("entry", entry.Key + ": " + entry.Value)); } return; } // just convert to a string as a fall back Trace.LogWarning("Unknown datatype [" + valueType + "] while trying to serialize a [" + this.GetType() + "] object."); node.Value = value.ToString(); }
/** * Loads a given object from node. * If the node contains a reference (i.e. an id or name but not the full object) then specify the reference type, * and library to search. * * Supported types. * * Primatives and strings * Data objects (referenced and full) * Arrays of primatives or strings * * Not implement yet: Lists of primatives, Lists or arrays of dataObjects. * */ protected object ReadObject(XElement node, string name, Type type, FieldReferenceType referenceType = FieldReferenceType.Full, IDataLibrary library = null) { XElement sourceNode = (node.Element(name)); if (sourceNode == null) { return(null); } // Primatives if (type.IsEnum) { return(ReadEnum(node, type, name)); } if (type == typeof(Color)) { return(ReadColor(node, name)); } if (type == typeof(bool)) { return(ReadBool(node, name)); } if (type.IsIntType()) { return(ReadInt(node, name)); } if (type == typeof(float)) { return(ReadFloat(node, name)); } if (type == typeof(string)) { return(ReadValue(node, name)); } if (type == typeof(DateTime)) { return(ReadDateTime(node, name)); } // Data object. if (type.IsSubclassOf(typeof(DataObject))) { switch (referenceType) { case FieldReferenceType.ID: case FieldReferenceType.Name: if (!type.IsSubclassOf(typeof(NamedDataObject))) { throw new Exception("Type must be subclass of NamedDataObject"); } if (referenceType == FieldReferenceType.ID) { return(library._byID(ReadInt(node, name))); } else { return(library._byName(ReadValue(node, name))); } case FieldReferenceType.Full: var result = Activator.CreateInstance(type); (result as DataObject).ReadNode(sourceNode); return(result); } } // Serializable if (typeof(iSerializable).IsAssignableFrom(type)) { var result = Activator.CreateInstance(type); (result as iSerializable).ReadNode(sourceNode); return(result); } // Arrays. if (type.IsArray) { switch (Type.GetTypeCode(type.GetElementType())) { case TypeCode.Boolean: return(ReadArray <bool>(node, name)); case TypeCode.Byte: return(ReadArray <byte>(node, name)); case TypeCode.Char: return(ReadArray <char>(node, name)); case TypeCode.DateTime: return(ReadArray <DateTime>(node, name)); case TypeCode.Double: return(ReadArray <double>(node, name)); case TypeCode.Single: return(ReadArray <Single>(node, name)); case TypeCode.Int16: return(ReadArray <Int16>(node, name)); case TypeCode.Int32: return(ReadArray <Int32>(node, name)); case TypeCode.Int64: return(ReadArray <Int64>(node, name)); case TypeCode.UInt16: return(ReadArray <UInt16>(node, name)); case TypeCode.UInt32: return(ReadArray <UInt32>(node, name)); case TypeCode.UInt64: return(ReadArrayULong(node, name)); } } // Try other types. if (type == typeof(BitArray)) { return(ReadBitArray(node, name)); } if (type.IsGenericList()) { throw new Exception("Sorry, auto loading for generic lists are not yet supported for [" + type + "]."); } throw new Exception("Can not read object of type " + type + " as it is not a known type."); }