using System.Reflection; using System.Collections.Generic; using System; using BehaviorDesigner.Runtime.Tasks; namespace BehaviorDesigner.Runtime { public class TaskUtility { public static char[] TrimCharacters = new char[] { '/' }; private static Dictionary typeLookup = new Dictionary(); private static List loadedAssemblies = null; private static Dictionary allFieldsLookup = new Dictionary(); private static Dictionary serializableFieldsLookup = new Dictionary(); private static Dictionary publicFieldsLookup = new Dictionary(); private static Dictionary> hasFieldLookup = new Dictionary>(); public static object CreateInstance(Type t) { #if NETFX_CORE && !UNITY_EDITOR if (t.IsGenericType() && t.GetGenericTypeDefinition() == typeof(Nullable<>)) { #else if (t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>)) { #endif t = Nullable.GetUnderlyingType(t); } #if NETFX_CORE && !UNITY_EDITOR return Activator.CreateInstance(t); #else return Activator.CreateInstance(t, true); #endif } public static FieldInfo[] GetAllFields(Type t) { FieldInfo[] fieldInfo = null; if (!allFieldsLookup.TryGetValue(t, out fieldInfo)) { var fieldList = ObjectPool.Get>(); fieldList.Clear(); #if NETFX_CORE && !UNITY_EDITOR var flags = System.BindingFlags.Public | System.BindingFlags.NonPublic | System.BindingFlags.Instance | System.BindingFlags.DeclaredOnly; #else var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly; #endif GetFields(t, ref fieldList, (int)flags); fieldInfo = fieldList.ToArray(); ObjectPool.Return(fieldList); allFieldsLookup.Add(t, fieldInfo); } return fieldInfo; } public static FieldInfo[] GetPublicFields(Type t) { FieldInfo[] fieldInfo = null; if (!publicFieldsLookup.TryGetValue(t, out fieldInfo)) { var fieldList = ObjectPool.Get>(); fieldList.Clear(); #if NETFX_CORE && !UNITY_EDITOR var flags = System.BindingFlags.Public | System.BindingFlags.Instance | System.BindingFlags.DeclaredOnly; #else var flags = BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly; #endif GetFields(t, ref fieldList, (int)flags); fieldInfo = fieldList.ToArray(); ObjectPool.Return(fieldList); publicFieldsLookup.Add(t, fieldInfo); } return fieldInfo; } public static FieldInfo[] GetSerializableFields(Type t) { FieldInfo[] fieldInfo = null; if (!serializableFieldsLookup.TryGetValue(t, out fieldInfo)) { var fieldList = ObjectPool.Get>(); fieldList.Clear(); #if NETFX_CORE && !UNITY_EDITOR var flags = System.BindingFlags.Public | System.BindingFlags.NonPublic | System.BindingFlags.Instance | System.BindingFlags.DeclaredOnly; #else var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly; #endif GetSerializableFields(t, fieldList, (int)flags); fieldInfo = fieldList.ToArray(); ObjectPool.Return(fieldList); serializableFieldsLookup.Add(t, fieldInfo); } return fieldInfo; } private static void GetSerializableFields(Type t, IList fieldList, int flags) { if (t == null || t.Equals(typeof(ParentTask)) || t.Equals(typeof(Task)) || t.Equals(typeof(SharedVariable))) return; #if NETFX_CORE && !UNITY_EDITOR var fields = t.GetFields((System.BindingFlags)flags); #else var fields = t.GetFields((BindingFlags)flags); #endif for (int i = 0; i < fields.Length; ++i) { if (!fields[i].IsPublic && !HasAttribute(fields[i], typeof(UnityEngine.SerializeField))) { continue; } fieldList.Add(fields[i]); } #if NETFX_CORE && !UNITY_EDITOR GetSerializableFields(t.BaseType(), fieldList, flags); #else GetSerializableFields(t.BaseType, fieldList, flags); #endif } private static void GetFields(Type t, ref List fieldList, int flags) { if (t == null || t.Equals(typeof(ParentTask)) || t.Equals(typeof(Task)) || t.Equals(typeof(SharedVariable))) return; #if NETFX_CORE && !UNITY_EDITOR var fields = t.GetFields((System.BindingFlags)flags); #else var fields = t.GetFields((BindingFlags)flags); #endif for (int i = 0; i < fields.Length; ++i) { fieldList.Add(fields[i]); } #if NETFX_CORE && !UNITY_EDITOR GetFields(t.BaseType(), ref fieldList, flags); #else GetFields(t.BaseType, ref fieldList, flags); #endif } public static Type GetTypeWithinAssembly(string typeName) { if (string.IsNullOrEmpty(typeName)) { return null; } Type type; // cache the results for quicker repeated lookup if (typeLookup.TryGetValue(typeName, out type)) { return type; } type = Type.GetType(typeName); // look in the loaded assemblies if (type == null) { if (loadedAssemblies == null) { #if NETFX_CORE && !UNITY_EDITOR loadedAssemblies = GetStorageFileAssemblies(typeName).Result; #else loadedAssemblies = new List(); var assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; ++i) { loadedAssemblies.Add(assemblies[i]); } #endif } for (int i = 0; i < loadedAssemblies.Count; ++i) { type = loadedAssemblies[i].GetType(typeName); if (type != null) { break; } } } if (type != null) { typeLookup.Add(typeName, type); } else if (typeName.Contains("BehaviorDesigner.Runtime.Tasks.Basic")) { // Updated the task namespace with Behavior Designer 1.6.1. return GetTypeWithinAssembly(typeName.Replace("BehaviorDesigner.Runtime.Tasks.Basic", "BehaviorDesigner.Runtime.Tasks.Unity")); } return type; } #if NETFX_CORE && !UNITY_EDITOR private static async System.Threading.Tasks.Task> GetStorageFileAssemblies(string typeName) { var loadedAssemblies = new List(); var folder = Windows.ApplicationModel.Package.Current.InstalledLocation; foreach (var file in await folder.GetFilesAsync()) { if (file.FileType.Equals(".dll")) { loadedAssemblies.Add(System.IO.Path.GetFileNameWithoutExtension(file.Name)); } } return loadedAssemblies; } #endif public static bool CompareType(Type t, string typeName) { var type = GetTypeWithinAssembly(typeName); if (type == null) { return false; } return t.Equals(type); } public static bool HasAttribute(FieldInfo field, Type attribute) { if (field == null) { return false; } bool hasAttribute; Dictionary typeLookup; if (!hasFieldLookup.TryGetValue(field, out typeLookup)) { typeLookup = new Dictionary(); hasFieldLookup.Add(field, typeLookup); } if (!typeLookup.TryGetValue(attribute, out hasAttribute)) { #if NETFX_CORE && !UNITY_EDITOR hasAttribute = field.GetCustomAttribute(attribute) != null; #else hasAttribute = field.GetCustomAttributes(attribute, false).Length > 0; #endif typeLookup.Add(attribute, hasAttribute); } return hasAttribute; } } }