//********************************** Banshee Engine (www.banshee3d.com) **************************************************//
//**************** Copyright (c) 2016 Marko Pintera (marko.pintera@gmail.com). All rights reserved. **********************//
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace BansheeEngine
{
/** @addtogroup Serialization
* @{
*/
#pragma warning disable 649
///
/// Allows you to access meta-data about a managed dictionary and its children. Similar to Reflection but simpler and
/// faster.
///
public sealed class SerializableDictionary : ScriptObject
{
private SerializableProperty.FieldType keyPropertyType;
private SerializableProperty.FieldType valuePropertyType;
private Type keyType;
private Type valueType;
private SerializableProperty parentProperty;
///
/// Type of serializable property used for the keys stored in the dictionary.
///
public SerializableProperty.FieldType KeyPropertyType
{
get { return keyPropertyType; }
}
///
/// Type of serializable property used for the values stored in the dictionary.
///
public SerializableProperty.FieldType ValuePropertyType
{
get { return valuePropertyType; }
}
///
/// Type used for of keys stored in the dictionary.
///
public Type KeyType
{
get { return keyType; }
}
///
/// Type used for values stored in the dictionary.
///
public Type ValueType
{
get { return valueType; }
}
///
/// Constructor for use by the runtime only.
///
/// C# type of the keys in the dictionary.
/// C# type of the values in the dictionary.
/// Property used for retrieving this entry.
private SerializableDictionary(Type keyType, Type valueType, SerializableProperty parentProperty)
{
this.parentProperty = parentProperty;
this.keyType = keyType;
this.valueType = valueType;
keyPropertyType = SerializableProperty.DetermineFieldType(keyType);
valuePropertyType = SerializableProperty.DetermineFieldType(valueType);
}
///
/// Returns a serializable property for the specified entry.
///
/// Dictionary key for the value to retrieve.
/// Serializable property that allows you to manipulate contents of the dictionary entry.
public KeyValuePair GetProperty(object key)
{
IDictionary dictionary = parentProperty.GetValue();
if (dictionary == null || !dictionary.Contains(key))
return new KeyValuePair(null, null);
SerializableProperty keyProperty;
{
SerializableProperty.Getter getter = () => key;
SerializableProperty.Setter setter = (object value) => {};
keyProperty = Internal_CreateKeyProperty(mCachedPtr);
keyProperty.Construct(KeyPropertyType, keyType, getter, setter);
}
SerializableProperty valueProperty;
{
SerializableProperty.Getter getter = () =>
{
IDictionary dict = parentProperty.GetValue();
if (dict != null)
return dict[key];
else
return null;
};
SerializableProperty.Setter setter = (object value) =>
{
IDictionary dict = parentProperty.GetValue();
if (dict != null)
dict[key] = value;
};
valueProperty = Internal_CreateValueProperty(mCachedPtr);
valueProperty.Construct(ValuePropertyType, valueType, getter, setter);
}
return new KeyValuePair(keyProperty, valueProperty);
}
///
/// Returns the total number of elements in the dictionary.
///
/// Total number of elements in the dictionary.
public int GetLength()
{
IDictionary dictionary = parentProperty.GetValue();
if (dictionary != null)
return dictionary.Count;
else
return 0;
}
///
/// Uses the provided path elements to find an dictionary element with the specified key, and returns a property
/// to the element, or to a child property of that element.
///
/// Path elements representing field names and keys to look for.
/// Index in the array to start the search at.
/// Property representing the final path element, or null if not found (key or property with that path
/// doesn't exist).
internal SerializableProperty FindProperty(PropertyPathElement[] pathElements, int elementIdx)
{
if (pathElements[elementIdx].key == null)
return null;
object key = null;
switch (KeyPropertyType)
{
case SerializableProperty.FieldType.String:
key = pathElements[elementIdx].key;
break;
case SerializableProperty.FieldType.Bool:
bool boolKey;
if (bool.TryParse(pathElements[elementIdx].key, out boolKey))
key = boolKey;
break;
case SerializableProperty.FieldType.Int:
int intKey;
if (int.TryParse(pathElements[elementIdx].key, out intKey))
key = intKey;
break;
case SerializableProperty.FieldType.Float:
float floatKey;
if (float.TryParse(pathElements[elementIdx].key, out floatKey))
key = floatKey;
break;
}
if (key == null)
return null;
SerializableProperty property = GetProperty(key).Value;
if (elementIdx == (pathElements.Length - 1))
return property;
if(property != null)
return property.FindProperty(pathElements, elementIdx + 1);
return null;
}
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern SerializableProperty Internal_CreateKeyProperty(IntPtr nativeInstance);
[MethodImpl(MethodImplOptions.InternalCall)]
private static extern SerializableProperty Internal_CreateValueProperty(IntPtr nativeInstance);
}
/** @} */
}