/// <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; if (obj == null) { return(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>(); if (dict != null) { foreach (var key in dict.Keys) { var 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 = new List <object>(); if (coll != null) { resultColl.AddRange(from object value in coll select GetWritablePlistObject(value.GetType(), value)); } result = resultColl; } else if (type.IsPrimitiveOrEnum()) { result = obj; } else { if (!_typeCache.ContainsKey(type)) { _typeCache[type] = new TypeCacheItem(type); } var cache = _typeCache[type]; var resultDict = new Dictionary <string, object>(); for (var i = 0; i < cache.Fields.Count; i++) { var field = cache.Fields[i]; var member = cache.FieldMembers[i]; var fieldValue = field.GetValue(obj); if (member.EmitDefaultValue || !field.FieldType.IsDefaultValue(fieldValue)) { resultDict[member.Name] = GetWritablePlistObject(field.FieldType, fieldValue); } } for (var i = 0; i < cache.Properties.Count; i++) { var property = cache.Properties[i]; var member = cache.PropertyMembers[i]; var 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) { return(null); } if (typeof(IPlistSerializable).IsAssignableFrom(type)) { if (plistDict == null) { return(null); } var serResult = (IPlistSerializable)Activator.CreateInstance(type); serResult.FromPlistDictionary(plistDict); } else if (typeof(IDictionary).IsAssignableFrom(type)) { if (plistDict == null) { return(null); } Type keyType = typeof(object), valueType = typeof(object); if (type.IsGenericType) { var 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 (var 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()) { if (!(obj is IEnumerable plistColl)) { return(null); } var valueType = typeof(object); var 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 (var value in plistColl) { listResult.Add(GetReadablePlistObject(valueType, value)); } result = isArray ? ((ArrayList)listResult).ToArray() : listResult; } else if (type.IsPrimitiveOrEnum()) { result = obj; } else { if (plistDict == null) { return(null); } if (!_typeCache.ContainsKey(type)) { _typeCache[type] = new TypeCacheItem(type); } var cache = _typeCache[type]; result = Activator.CreateInstance(type); for (var i = 0; i < cache.Fields.Count; i++) { var field = cache.Fields[i]; var member = cache.FieldMembers[i]; if (plistDict.Contains(member.Name)) { field.SetValue(result, GetReadablePlistObject(field.FieldType, plistDict[member.Name])); } } for (var i = 0; i < cache.Properties.Count; i++) { var property = cache.Properties[i]; var member = cache.PropertyMembers[i]; if (plistDict.Contains(member.Name)) { property.SetValue(result, GetReadablePlistObject(property.PropertyType, plistDict[member.Name]), null); } } } return(result); }