/// <summary> /// Serializes the specified <see cref="Object"/>. Can be <see langword="null"/>. /// </summary> /// <param name="obj">Specifies the <see cref="Object"/> to serialize.</param> /// <returns></returns> public NuGenPropertyInfoCollection SerializeObject(object obj) { if (obj == null) { return null; } if (_graph[obj] == -1) { _graph.Add(obj); } NuGenPropertyInfoCollection properties = new NuGenPropertyInfoCollection(); PropertyDescriptorCollection descriptors = TypeDescriptor.GetProperties(obj); /* If no public properties found return null. */ if ((descriptors == null) || (descriptors.Count == 0)) { return null; } if (this.SortProperties) { descriptors = descriptors.Sort(); } /* * Serialize public properties. */ for (int i = 0; i < descriptors.Count; i++) { this.OnSerializing(EventArgs.Empty); PropertyDescriptor descriptor = descriptors[i]; NuGenSerializationVisibilityAttribute attribute = (NuGenSerializationVisibilityAttribute)descriptor.Attributes[typeof(NuGenSerializationVisibilityAttribute)]; /* This is the default value for the property that is not marked with * NuGenSerializationVisibilityAttribute attribute. */ NuGenSerializationVisibility visibility = NuGenSerializationVisibility.Content; object propertyDefaultValue = NuGenSerializer.GetDefaultValue(descriptor); string propertyName = descriptor.Name; object propertyValue = descriptor.GetValue(obj); /* If the property is marked with the NuGenSerializationVisibilityAttribute attribute... */ if (attribute != null) { /* Skip properties that are not visible for the serializer. */ if (attribute.Visibility == NuGenSerializationVisibility.Hidden) { continue; } visibility = attribute.Visibility; } /* If the property is not marked with the NuGenSerializationVisibilityAttribute attribute... */ else { if ( (descriptor.SerializationVisibility == DesignerSerializationVisibility.Content) && !(propertyValue is IList) && !(descriptor.PropertyType.IsEnum) ) { visibility = NuGenSerializationVisibility.Reference; } else if ( !(descriptor.ShouldSerializeValue(obj)) || (descriptor.SerializationVisibility == DesignerSerializationVisibility.Hidden) ) { continue; } } NuGenPropertyInfo propertyInfo = null; if (propertyValue == null) { propertyInfo = new NuGenPropertyInfo( propertyName, propertyValue, propertyDefaultValue, true, false, false ); } else { switch (visibility) { case NuGenSerializationVisibility.Reference: { propertyInfo = new NuGenPropertyInfo( propertyName, propertyValue, propertyDefaultValue, true, true, false ); _references.Add(propertyInfo); break; } case NuGenSerializationVisibility.Content: { /* * Automatically determine if the marked property is a collection. */ if (propertyValue is IList) { propertyInfo = new NuGenPropertyInfo( propertyName, propertyValue, propertyDefaultValue, false, false, true ); propertyInfo.Count = this.SerializeList( propertyInfo.Properties, propertyValue ); } else { propertyInfo = new NuGenPropertyInfo( propertyName, propertyValue, propertyDefaultValue, false, false, false ); } break; } case NuGenSerializationVisibility.Class: { if (!propertyValue.GetType().IsClass) { throw new InvalidCastException( string.Format(CultureInfo.InvariantCulture, Properties.Resources.InvalidCast_NotClass, propertyName) ); } NuGenReferenceIgnoreAttribute[] ignoreAttributes = (NuGenReferenceIgnoreAttribute[])descriptor.PropertyType.GetCustomAttributes(typeof(NuGenReferenceIgnoreAttribute), false); int valueInitial = _graph[propertyValue]; if ((valueInitial == -1) || (ignoreAttributes.Length > 0)) { _graph.Add(propertyValue); int valueAfterAdd = _graph[propertyValue]; if ( (this.CheckSerializable) && (propertyValue is INuGenSerializable) ) { propertyInfo = new NuGenPropertyInfo( propertyName, propertyValue, propertyDefaultValue, true, false, false ); propertyInfo.IsSerializable = true; } else { propertyInfo = new NuGenPropertyInfo( propertyName, propertyValue, propertyDefaultValue, true, false, false ); NuGenPropertyInfoCollection innerProperties = this.SerializeObject(propertyValue); if (innerProperties != null) { propertyInfo.Properties.AddRange(innerProperties); } } propertyInfo.ReferenceCode = valueAfterAdd; } else { propertyInfo = new NuGenPropertyInfo( propertyName, propertyValue, propertyDefaultValue, true, true, false ); propertyInfo.ReferenceCode = valueInitial; } break; } } } if (propertyInfo != null) { properties.Add(propertyInfo); } } return properties; }
private NuGenPropertyInfoCollection DeserializeObject(XmlTextReader xmlTextReader) { Debug.Assert(xmlTextReader != null, "xmlTextReader != null"); NuGenPropertyInfoCollection propertyInfoCollection = new NuGenPropertyInfoCollection(); xmlTextReader.Read(); while (!xmlTextReader.EOF) { if (xmlTextReader.IsStartElement()) { this.OnDeserializing(EventArgs.Empty); string propertyString = xmlTextReader.Name; bool isKey = xmlTextReader.GetAttribute(Resources.XmlAttribute_IsKey) == Resources.XmlValue_True; bool isRef = xmlTextReader.MoveToAttribute(Resources.XmlAttribute_IsRef); bool isList = xmlTextReader.MoveToAttribute(Resources.XmlAttribute_IsList); NuGenPropertyInfo propertyInfo = new NuGenPropertyInfo( XmlConvert.DecodeName(NuGenSerializer.GetPropertyFromString(propertyString)), null, isKey, isRef, isList ); if (xmlTextReader.GetAttribute(Resources.XmlAttribute_IsNull) == Resources.XmlValue_True) { propertyInfo.Value = null; } else if (xmlTextReader.GetAttribute(Resources.XmlAttribute_IsSer) != null) { string refAttrValue = xmlTextReader.GetAttribute(Resources.XmlAttribute_Ref); if (refAttrValue != null) { propertyInfo.ReferenceCode = int.Parse(refAttrValue, CultureInfo.InvariantCulture); } string typeAttrValue = xmlTextReader.GetAttribute(Resources.XmlAttribute_Type); Type typeFromAttr = NuGenSerializer.StringToType[typeAttrValue] as Type; if (typeFromAttr == null) { propertyInfo.Value = NuGenActivator.CreateObject(typeAttrValue); } else { propertyInfo.Value = NuGenActivator.CreateObject(typeFromAttr); } propertyInfo.IsSerializable = true; INuGenSerializable serializable = (INuGenSerializable)propertyInfo.Value; serializable.Deserialize(_converter, xmlTextReader); _graph.Add(serializable, propertyInfo.ReferenceCode); } else if (propertyInfo.IsReference) { propertyInfo.ReferenceCode = int.Parse(xmlTextReader.GetAttribute(Resources.XmlAttribute_IsRef), CultureInfo.InvariantCulture); } else if (propertyInfo.IsList) { propertyInfo.Count = int.Parse(xmlTextReader.GetAttribute(Resources.XmlAttribute_Count), CultureInfo.InvariantCulture); if ((propertyInfo.Count > 0) && !xmlTextReader.IsEmptyElement) { propertyInfo.Properties = this.DeserializeObject(xmlTextReader); } } else if (!propertyInfo.IsKey) { if (xmlTextReader.GetAttribute(Resources.XmlAttribute_IsImage) == Resources.XmlValue_True) { int bufferLength = int.Parse(xmlTextReader.GetAttribute(Resources.XmlAttribute_Length), CultureInfo.InvariantCulture); byte[] buffer = new byte[bufferLength]; xmlTextReader.ReadBase64(buffer, 0, bufferLength); propertyInfo.Value = NuGenImageConverter.BytesToImage(buffer); } else if (xmlTextReader.GetAttribute(Resources.XmlAttribute_IsEmfImage) == Resources.XmlValue_True) { int bufferLength = int.Parse(xmlTextReader.GetAttribute(Resources.XmlAttribute_Length), CultureInfo.InvariantCulture); byte[] buffer = new byte[bufferLength]; xmlTextReader.ReadBase64(buffer, 0, bufferLength); propertyInfo.Value = NuGenMetafileConverter.BytesToMetafile(buffer); } else { propertyInfo.Value = xmlTextReader.ReadString(); } } else if (propertyInfo.IsKey) { string attrRef = xmlTextReader.GetAttribute(Resources.XmlAttribute_Ref); if (attrRef != null) { propertyInfo.ReferenceCode = int.Parse(attrRef, CultureInfo.InvariantCulture); } string typeAttr = xmlTextReader.GetAttribute(Resources.XmlAttribute_Type); Type typeFromAttr = NuGenSerializer.StringToType[typeAttr] as Type; if (typeFromAttr == null) { propertyInfo.Value = NuGenActivator.CreateObject(typeAttr); } else { propertyInfo.Value = NuGenActivator.CreateObject(typeFromAttr); } if (!xmlTextReader.IsEmptyElement) { propertyInfo.Properties = this.DeserializeObject(xmlTextReader); } } propertyInfoCollection.Add(propertyInfo); } else if (xmlTextReader.NodeType == XmlNodeType.EndElement) { return propertyInfoCollection; } xmlTextReader.Read(); } return propertyInfoCollection; }
/// <summary> /// Serializes the specified list. /// </summary> /// <param name="properties">Specifies the <see cref="NuGenPropertyInfoCollection"/> to be filled /// with the elements of the specified list.</param> /// <param name="list">Specifies the list to serialize.</param> /// <returns>Returns the number of elements in the specified list.</returns> private int SerializeList(NuGenPropertyInfoCollection properties, object list) { if (list == null) { return 0; } Debug.Assert(properties != null, "properties != null"); Debug.Assert(list is IList, "list is IList"); int count = 0; foreach (object item in (IList)list) { this.OnSerializing(EventArgs.Empty); if ( (item.GetType().IsPrimitive) || (item is string) || (this.IsContent(item)) ) { properties.Add( new NuGenPropertyInfo(Resources.XmlAttribute_Value, item, false, false, false) ); } else { int index = _graph[item]; if (index == -1) { _graph.Add(item); NuGenPropertyInfo propertyInfo = null; if (this.CheckSerializable && (item is INuGenSerializable)) { propertyInfo = new NuGenPropertyInfo( string.Format(CultureInfo.InvariantCulture, "{0}{1}", Resources.XmlTag_Item, (count + 1).ToString(CultureInfo.InvariantCulture)), item, true, false, false ); propertyInfo.IsSerializable = true; } else { string propertyName = Resources.XmlTag_Item; PropertyInfo namePropertyInfo = item.GetType().GetProperty("Name"); if (namePropertyInfo != null) { string namePropertyValue = (string)namePropertyInfo.GetValue(item, null); if (!string.IsNullOrEmpty(namePropertyValue)) { propertyName = namePropertyValue; } } propertyInfo = new NuGenPropertyInfo( string.Format(CultureInfo.InvariantCulture, "{0}{1}", propertyName, (count + 1).ToString(CultureInfo.InvariantCulture)), item, true, false, false ); propertyInfo.Properties.AddRange(this.SerializeObject(item)); } Debug.Assert(propertyInfo != null, "propertyInfo != null"); propertyInfo.ReferenceCode = _graph[item]; properties.Add(propertyInfo); } else { NuGenPropertyInfo propertyInfo = new NuGenPropertyInfo( Resources.XmlTag_Item, item, true, true, false ); propertyInfo.ReferenceCode = index; properties.Add(propertyInfo); } } count++; } return count; }