| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Linq;
- using System.Runtime.CompilerServices;
- using System.Text;
- namespace BansheeEngine
- {
- /// <summary>
- /// Allows you to transparently retrieve and set values of an entry, whether that entry is an object field or
- /// an array/list/dictionary entry.
- /// </summary>
- public sealed class SerializableProperty : ScriptObject
- {
- /// <summary>
- /// Object field types support by the serializable property.
- /// </summary>
- public enum FieldType
- {
- Int,
- Float,
- Bool,
- String,
- Color,
- Vector2,
- Vector3,
- Vector4,
- GameObjectRef,
- ResourceRef,
- Object,
- Array,
- List,
- Dictionary
- }
- public delegate object Getter();
- public delegate void Setter(object value);
- private FieldType type;
- private Type internalType;
- private Getter getter;
- private Setter setter;
- /// <summary>
- /// Constructor for internal use by the native code.
- /// </summary>
- private SerializableProperty()
- { }
- /// <summary>
- /// Creates a new serializable property.
- /// </summary>
- /// <param name="type">Type of data the property contains.</param>
- /// <param name="internalType">Type of data the property contains, as C# type.</param>
- /// <param name="getter">Method that allows you to retrieve contents of the property.</param>
- /// <param name="setter">Method that allows you to set contents of the property</param>
- public SerializableProperty(FieldType type, Type internalType, Getter getter, Setter setter)
- {
- this.type = type;
- this.internalType = internalType;
- this.getter = getter;
- this.setter = setter;
- }
- /// <summary>
- /// Finalizes construction of the serializable property. Must be called after creation.
- /// </summary>
- /// <param name="type">Type of data the property contains.</param>
- /// <param name="internalType">Type of data the property contains, as C# type.</param>
- /// <param name="getter">Method that allows you to retrieve contents of the property.</param>
- /// <param name="setter">Method that allows you to set contents of the property</param>
- internal void Construct(FieldType type, Type internalType, Getter getter, Setter setter)
- {
- this.type = type;
- this.internalType = internalType;
- this.getter = getter;
- this.setter = setter;
- }
- /// <summary>
- /// Returns type of data the property contains.
- /// </summary>
- public FieldType Type
- {
- get { return type; }
- }
- /// <summary>
- /// Returns type of data the property contains, as C# type.
- /// </summary>
- public Type InternalType
- {
- get { return internalType; }
- }
- /// <summary>
- /// Is the containing type a value type (true), or a reference type (false).
- /// </summary>
- public bool IsValueType
- {
- get { return internalType.IsValueType; }
- }
- /// <summary>
- /// Retrieves the value contained in the property.
- /// </summary>
- /// <typeparam name="T">Type of the value to retrieve. Caller must ensure the type matches the property type.</typeparam>
- /// <returns>Value of the property.</returns>
- public T GetValue<T>()
- {
- if (!typeof(T).IsAssignableFrom(internalType))
- throw new Exception("Attempted to retrieve a serializable value using an invalid type. Provided type: " + typeof(T) + ". Needed type: " + internalType);
- return (T)getter();
- }
- /// <summary>
- /// Retrieves a copy of the value contained in the property.
- /// </summary>
- /// <typeparam name="T">Type of the value to retrieve. Caller must ensure the type matches the property type.</typeparam>
- /// <returns>A deep copy of the value of the property.</returns>
- public T GetValueCopy<T>()
- {
- if (!typeof(T).IsAssignableFrom(internalType))
- throw new Exception("Attempted to retrieve a serializable value using an invalid type. Provided type: " + typeof(T) + ". Needed type: " + internalType);
- return (T)Internal_CloneManagedInstance(mCachedPtr, getter());
- }
- /// <summary>
- /// Changes the value of the property.
- /// </summary>
- /// <typeparam name="T">Type of the value to set. Caller must ensure the type matches the property type.</typeparam>
- /// <param name="value">New value to assign to the property.</param>
- public void SetValue<T>(T value)
- {
- if (!typeof(T).IsAssignableFrom(internalType))
- throw new Exception("Attempted to set a serializable value using an invalid type. Provided type: " + typeof(T) + ". Needed type: " + internalType);
- setter(value);
- }
- /// <summary>
- /// Returns a serializable object wrapper around the value contained in the property.
- /// </summary>
- /// <returns>Serializable object wrapper around the value contained in the property.</returns>
- public SerializableObject GetObject()
- {
- if (type != FieldType.Object)
- throw new Exception("Attempting to retrieve object information from a field that doesn't contain an object.");
- return Internal_CreateObject(mCachedPtr);
- }
- /// <summary>
- /// Returns a serializable array around the value contained in the property. Caller must ensure the property
- /// contains an array.
- /// </summary>
- /// <returns>Serializable array around the value contained in the property.</returns>
- public SerializableArray GetArray()
- {
- if (type != FieldType.Array)
- throw new Exception("Attempting to retrieve array information from a field that doesn't contain an array.");
- return Internal_CreateArray(mCachedPtr);
- }
- /// <summary>
- /// Returns a serializable list around the value contained in the property. Caller must ensure the property
- /// contains a list.
- /// </summary>
- /// <returns>Serializable list around the value contained in the property.</returns>
- public SerializableList GetList()
- {
- if (type != FieldType.List)
- throw new Exception("Attempting to retrieve array information from a field that doesn't contain a list.");
- return Internal_CreateList(mCachedPtr);
- }
- /// <summary>
- /// Returns a serializable dictionary around the value contained in the property. Caller must ensure the property
- /// contains a dictionary.
- /// </summary>
- /// <returns>Serializable dictionary around the value contained in the property.</returns>
- public SerializableDictionary GetDictionary()
- {
- if (type != FieldType.Dictionary)
- throw new Exception("Attempting to retrieve array information from a field that doesn't contain a dictionary.");
- return Internal_CreateDictionary(mCachedPtr);
- }
- /// <summary>
- /// Creates a new instance of the type wrapped by this property.
- /// </summary>
- /// <typeparam name="T">Type of the object to create. Caller must ensure the type matches the property type and that
- /// the property wraps an object.</typeparam>
- /// <returns>A new instance of an object of type <typeparamref name="T"/>.</returns>
- public T CreateObjectInstance<T>()
- {
- if (type != FieldType.Object)
- throw new Exception("Attempting to retrieve object information from a field that doesn't contain an object.");
- return (T)Internal_CreateManagedObjectInstance(mCachedPtr);
- }
- /// <summary>
- /// Creates a new instance of the array wrapped by this property. Caller must ensure this property contains an array.
- /// </summary>
- /// <param name="lengths">Size of each dimension of the array. Number of dimensions must match the number
- /// of dimensions in the array wrapped by this property.</param>
- /// <returns>A new array containing the same element type as the array wrapped by this property, of
- /// <paramref name="lengths"/> sizes.</returns>
- public Array CreateArrayInstance(int[] lengths)
- {
- if (type != FieldType.Array)
- throw new Exception("Attempting to retrieve array information from a field that doesn't contain an array.");
- return Internal_CreateManagedArrayInstance(mCachedPtr, lengths);
- }
- /// <summary>
- /// Creates a new instance of the list wrapped by this property. Caller must ensure this property contains a list.
- /// </summary>
- /// <param name="length">Size of the list.</param>
- /// <returns>A new list containing the same element type as the list wrapped by this property, of
- /// <paramref name="length"/> size.</returns>
- public IList CreateListInstance(int length)
- {
- if (type != FieldType.List)
- throw new Exception("Attempting to retrieve array information from a field that doesn't contain a list.");
- return Internal_CreateManagedListInstance(mCachedPtr, length);
- }
- /// <summary>
- /// Creates a new instance of the dictionary wrapped by this property. Caller must ensure this property contains
- /// a dictionary.
- /// </summary>
- /// <returns>A new dictionary containing the same key/value types as the dictionary wrapped by this property.
- /// </returns>
- public IDictionary CreateDictionaryInstance()
- {
- if (type != FieldType.Dictionary)
- throw new Exception("Attempting to retrieve array information from a field that doesn't contain a dictionary.");
- return Internal_CreateManagedDictionaryInstance(mCachedPtr);
- }
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern SerializableObject Internal_CreateObject(IntPtr nativeInstance);
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern SerializableArray Internal_CreateArray(IntPtr nativeInstance);
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern SerializableList Internal_CreateList(IntPtr nativeInstance);
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern SerializableDictionary Internal_CreateDictionary(IntPtr nativeInstance);
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern object Internal_CreateManagedObjectInstance(IntPtr nativeInstance);
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern Array Internal_CreateManagedArrayInstance(IntPtr nativeInstance, int[] lengths);
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern IList Internal_CreateManagedListInstance(IntPtr nativeInstance, int length);
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern IDictionary Internal_CreateManagedDictionaryInstance(IntPtr nativeInstance);
- [MethodImpl(MethodImplOptions.InternalCall)]
- private static extern object Internal_CloneManagedInstance(IntPtr nativeInstance, object original);
- /// <summary>
- /// Converts a C# type into Banshee-specific serialization type.
- /// </summary>
- /// <param name="internalType">C# to convert.</param>
- /// <returns>Banshee-specific serialization type. Throws an exception if matching type cannot be found.</returns>
- public static FieldType DetermineFieldType(Type internalType)
- {
- if (!internalType.IsArray)
- {
- if (internalType == typeof (Byte))
- return FieldType.Int;
- else if (internalType == typeof (SByte))
- return FieldType.Int;
- else if (internalType == typeof (Int16))
- return FieldType.Int;
- else if (internalType == typeof (UInt16))
- return FieldType.Int;
- else if (internalType == typeof (Int32))
- return FieldType.Int;
- else if (internalType == typeof (UInt32))
- return FieldType.Int;
- else if (internalType == typeof (Int64))
- return FieldType.Int;
- else if (internalType == typeof (UInt64))
- return FieldType.Int;
- else if (internalType == typeof (bool))
- return FieldType.Bool;
- else if (internalType == typeof (float))
- return FieldType.Float;
- else if (internalType == typeof (double))
- return FieldType.Float;
- else if (internalType == typeof (string))
- return FieldType.String;
- else if (internalType == typeof (Vector2))
- return FieldType.Vector2;
- else if (internalType == typeof (Vector3))
- return FieldType.Vector3;
- else if (internalType == typeof (Vector4))
- return FieldType.Vector4;
- else if (internalType == typeof (Color))
- return FieldType.Color;
- else if (internalType.IsSubclassOf(typeof (GameObject)))
- return FieldType.GameObjectRef;
- else if (internalType.IsSubclassOf(typeof (Resource)))
- return FieldType.ResourceRef;
- else if (internalType.IsGenericType)
- {
- Type genericType = internalType.GetGenericTypeDefinition();
- if (genericType == typeof (List<>))
- {
- return FieldType.List;
- }
- else if (genericType == typeof (Dictionary<,>))
- {
- return FieldType.Dictionary;
- }
- // Shouldn't happen because native code should only supply us with supported types
- throw new Exception("Cannot determine field type. Found an unsupported generic type.");
- }
- // Otherwise the type must be an object, unless some error occurred
- return FieldType.Object;
- }
- return FieldType.Array;
- }
- }
- }
|