void SerializeClass(object instance, Type type, IKey inKey, int inInheriteDeep, ILogPrinter inLogger) { MethodInfo mi = type.GetMethod("SerializationToCscd", new Type[] { typeof(CascadeParser.IKey), typeof(CascadeParser.ILogPrinter) }); if (mi != null) { if (string.IsNullOrEmpty(inKey.GetName())) { inKey.SetName("Value"); } mi.Invoke(instance, new object[] { inKey, inLogger }); return; } MemberInfo[] member_infos = _reflectionProvider.GetSerializableMembers(type); foreach (MemberInfo memberInfo in member_infos) { object value = _reflectionProvider.GetValue(memberInfo, instance); if (value == null) { continue; } SCustomMemberParams member_params = GetMemberParams(memberInfo); if (member_params.DefaultValue != null) { if (member_params.DefaultValue.GetType() != value.GetType()) { LogError(inLogger, string.Format("DefaultValue and member {2} of class {3} have difference types: {0} and {1}", member_params.DefaultValue.GetType().Name, value.GetType().Name, member_params.Name, type.Name)); } else if (member_params.DefaultValue.Equals(value)) { continue; } } else if (ReflectionHelper.IsDefault(value, _reflectionProvider, inLogger)) { continue; } IKey child = inKey.CreateChildKey(member_params.ChangedName); Type real_type = value.GetType(); Type member_type = memberInfo.GetMemberType(); if (member_params.Converter != null && member_params.Converter.CanConvert(real_type)) { member_params.Converter.WriteKey(child, value, inLogger); } else { Serialize(value, real_type, child, 0, inLogger); } // Write the runtime type if different (except nullables since they get unboxed) if (real_type != member_type && !member_type.IsNullable()) { IKey obj_type_key = child.CreateChildKey("RealObjectType"); obj_type_key.AddValue(real_type.FullName); obj_type_key.AddValue(real_type.Assembly.FullName); } } }
SerializedObject SerializeInternal(string name, object instance, Type declaredType) { SerializedObject child; var type = instance == null ? declaredType : instance.GetType(); // Atomic values if (instance == null || IsAtomic(type)) { child = new SerializedAtom { Name = name, Type = type, Value = instance }; } else if (IsXmlType(type)) { using (var sw = new StringWriter()) using (var xw = XmlWriter.Create(sw, new XmlWriterSettings { ConformanceLevel = ConformanceLevel.Fragment })) { if (xw == null) { throw new Exception("SerializeInternal error. xw is null"); } xw.WriteStartElement("root"); var xmlSerializable = instance as IXmlSerializable; if (xmlSerializable == null) { throw new Exception("SerializeInternal error. xmlSerializable is null"); } xmlSerializable.WriteXml(xw); xw.WriteEndElement(); xw.Flush(); sw.Flush(); child = new SerializedXml { Name = name, Type = type, Value = sw.ToString() }; } } else if (IsSerializable(type)) { using (var ms = new MemoryStream()) { serializer.Serialize(ms, instance); ms.Flush(); child = new SerializedXml() { Name = name, Type = type, Value = Encoding.Default.GetString(ms.ToArray()) }; } } // Dictionaries else if (type.IsGenericDictionary()) { var dictionary = instance as IDictionary; if (dictionary == null) { throw new Exception("SerializeInternal error. dictionary is null"); } var genericArguments = dictionary.GetType().GetGenericArguments(); var keyDeclaredType = genericArguments[0]; var valueDeclaredType = genericArguments[1]; child = new SerializedAggregate { Name = name }; var childAggregation = child as SerializedAggregate; foreach (var key in dictionary.Keys) { childAggregation.Children.Add( SerializeInternal(null, key, keyDeclaredType), SerializeInternal(null, dictionary[key], valueDeclaredType)); } } // Arrays, lists and sets (any collection excluding dictionaries) else if (type.IsGenericCollection()) { var collection = instance as IEnumerable; if (collection == null) { throw new Exception("SerializeInternal error. dictionary is null"); } var declaredItemType = type.IsArray ? type.GetElementType() : type.GetGenericArguments()[0]; child = new SerializedCollection { Name = name }; var childCollection = child as SerializedCollection; foreach (var item in collection) { childCollection.Items.Add(SerializeInternal(null, item, declaredItemType)); } } // Everything else (serialized with recursive property reflection) else { child = new SerializedAggregate { Name = name }; var childAggregation = child as SerializedAggregate; foreach (var memberInfo in _reflectionProvider.GetSerializableMembers(type)) { var memberAttr = _reflectionProvider.GetSingleAttributeOrDefault <SerializationAttribute>(memberInfo); // Make sure we want it serialized if (memberAttr.Ignore) { continue; } var memberType = memberInfo.GetMemberType(); object value = null; try { value = _reflectionProvider.GetValue(memberInfo, instance); } catch { } // Optional properties are skipped when serializing a default or null value if (!memberAttr.Required && (value == null || IsDefault(value, (memberInfo as PropertyInfo) != null ? (memberInfo as PropertyInfo).PropertyType : (memberInfo as FieldInfo).FieldType))) { continue; } // If no property name is defined, use the short type name var memberName = memberAttr.Name ?? memberInfo.Name; childAggregation.Children.Add(memberName, SerializeInternal(memberName, value, memberType)); } } // Write the runtime type if different (except nullables since they get unboxed) //if (!declaredType.IsNullable() && type != declaredType) child.Type = type.HasParameterlessConstructor() ? type : declaredType; return(child); }