/// <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)) { IDictionary dict = obj as IDictionary; Dictionary <object, object> resultDict = new Dictionary <object, object>(); foreach (object key in dict.Keys) { object value = dict[key]; resultDict[this.GetWritablePlistObject(key.GetType(), key)] = this.GetWritablePlistObject(value.GetType(), value); } result = resultDict; } else if (type.IsCollection()) { IEnumerable coll = obj as IEnumerable; List <object> resultColl = new List <object>(); foreach (object value in coll) { resultColl.Add(this.GetWritablePlistObject(value.GetType(), value)); } result = resultColl; } else if (type.IsPrimitiveOrEnum()) { result = obj; } else { if (!this.typeCache.ContainsKey(type)) { this.typeCache[type] = new TypeCacheItem(type); } TypeCacheItem cache = this.typeCache[type]; Dictionary <string, object> 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] = this.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] = this.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; IDictionary plistDict = obj as IDictionary; if (obj != null) { if (typeof(IPlistSerializable).IsAssignableFrom(type)) { if (plistDict != null) { IPlistSerializable 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]; } IDictionary 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[this.GetReadablePlistObject(keyType, key)] = this.GetReadablePlistObject(valueType, plistDict[key]); } result = dictResult; } } else if (type.IsCollection()) { IEnumerable 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(this.GetReadablePlistObject(valueType, value)); } result = isArray ? ((ArrayList)listResult).ToArray() : listResult; } } else if (type.IsPrimitiveOrEnum()) { result = obj; } else { if (plistDict != null) { if (!this.typeCache.ContainsKey(type)) { this.typeCache[type] = new TypeCacheItem(type); } TypeCacheItem cache = this.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, this.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, this.GetReadablePlistObject(property.PropertyType, plistDict[member.Name]), null); } } } } } return(result); }