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;
}