/// <summary> /// Gets the writable plist value of the given object identified by the specified type. /// </summary> /// <param name="type">The of the object.</param> /// <param name="obj">The object to get the plist value of.</param> /// <returns>The plist value of the given object.</returns> private object GetWritablePlistObject(Type type, object obj) { object result = null; if (obj != null) { if (typeof(IPlistSerializable).IsAssignableFrom(type)) { result = ((IPlistSerializable)obj).ToPlistDictionary(); } else if (typeof(IDictionary).IsAssignableFrom(type)) { var dict = obj as IDictionary; var resultDict = new Dictionary <object, object>(); foreach (object key in dict.Keys) { object value = dict[key]; resultDict[GetWritablePlistObject(key.GetType(), key)] = GetWritablePlistObject(value.GetType(), value); } result = resultDict; } else if (type.IsCollection()) { var coll = obj as IEnumerable; var resultColl = (from object value in coll select GetWritablePlistObject(value.GetType(), value)).ToList(); result = resultColl; } else if (type.IsPrimitiveOrEnum()) { result = obj; } else { if (!typeCache.ContainsKey(type)) { typeCache[type] = new TypeCacheItem(type); } TypeCacheItem cache = typeCache[type]; var resultDict = new Dictionary <string, object>(); for (int i = 0; i < cache.Fields.Count; i++) { FieldInfo field = cache.Fields[i]; DataMemberAttribute member = cache.FieldMembers[i]; object fieldValue = field.GetValue(obj); if (member.EmitDefaultValue || !field.FieldType.IsDefaultValue(fieldValue)) { resultDict[member.Name] = GetWritablePlistObject(field.FieldType, fieldValue); } } for (int i = 0; i < cache.Properties.Count; i++) { PropertyInfo property = cache.Properties[i]; DataMemberAttribute member = cache.PropertyMembers[i]; object propertyValue = property.GetValue(obj, null); if (member.EmitDefaultValue || !property.PropertyType.IsDefaultValue(propertyValue)) { resultDict[member.Name] = GetWritablePlistObject(property.PropertyType, propertyValue); } } result = resultDict; } } return(result); }
/// <summary> /// Gets the readable plist value of the given object identified by the specified type. /// </summary> /// <param name="type">The type the object is expected to have after being de-serialized.</param> /// <param name="obj">The raw plist object value.</param> /// <returns>A readable plist object value.</returns> private object GetReadablePlistObject(Type type, object obj) { object result = null; var plistDict = obj as IDictionary; if (obj != null) { if (typeof(IPlistSerializable).IsAssignableFrom(type)) { if (plistDict != null) { var serResult = (IPlistSerializable)Activator.CreateInstance(type); serResult.FromPlistDictionary(plistDict); } } else if (typeof(IDictionary).IsAssignableFrom(type)) { if (plistDict != null) { Type keyType = typeof(object), valueType = typeof(object); if (type.IsGenericType) { Type[] args = type.GetGenericArguments(); keyType = args[0]; valueType = args[1]; } var dictResult = (IDictionary)(type.IsInterface ? Activator.CreateInstance(typeof(Dictionary <,>).MakeGenericType(keyType, valueType)) : Activator.CreateInstance(type)); foreach (object key in plistDict.Keys) { if (!type.IsGenericType) { keyType = key.GetType(); valueType = plistDict[key] != null ? plistDict[key].GetType() : typeof(object); } dictResult[GetReadablePlistObject(keyType, key)] = GetReadablePlistObject(valueType, plistDict[key]); } result = dictResult; } } else if (type.IsCollection()) { var plistColl = obj as IEnumerable; if (plistColl != null) { Type valueType = typeof(object); bool isArray = false; IList listResult; if (type.IsGenericType) { valueType = type.GetGenericArguments()[0]; } else if (typeof(Array).IsAssignableFrom(type)) { valueType = type.GetElementType(); isArray = true; } if (isArray) { listResult = new ArrayList(); } else { // TODO: The default DataContractSerializer uses an informal protocal requiring a method named "Add()" // rather than requiring concrete collection types to implement IList. listResult = (IList)(type.IsInterface ? Activator.CreateInstance(typeof(List <>).MakeGenericType(valueType)) : Activator.CreateInstance(type)); } foreach (object value in plistColl) { listResult.Add(GetReadablePlistObject(valueType, value)); } result = isArray ? ((ArrayList)listResult).ToArray() : listResult; } } else if (type.IsPrimitiveOrEnum()) { result = obj; } else if (plistDict != null) { if (!typeCache.ContainsKey(type)) { typeCache[type] = new TypeCacheItem(type); } TypeCacheItem cache = typeCache[type]; result = Activator.CreateInstance(type); for (int i = 0; i < cache.Fields.Count; i++) { FieldInfo field = cache.Fields[i]; DataMemberAttribute member = cache.FieldMembers[i]; if (plistDict.Contains(member.Name)) { field.SetValue(result, GetReadablePlistObject(field.FieldType, plistDict[member.Name])); } } for (int i = 0; i < cache.Properties.Count; i++) { PropertyInfo property = cache.Properties[i]; DataMemberAttribute member = cache.PropertyMembers[i]; if (plistDict.Contains(member.Name)) { property.SetValue(result, GetReadablePlistObject(property.PropertyType, plistDict[member.Name]), null); } } } } return(result); }