using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using BF = System.Reflection.BindingFlags;
using UnityExplorer.Core.Runtime;
using System.Text;
namespace UnityExplorer
{
public class ReflectionUtility
{
// The Instance and instance methods are not for public use, they're only so IL2CPP can override.
// This class and the Extensions class expose static methods to use instead.
public const BF FLAGS = BF.Public | BF.Instance | BF.NonPublic | BF.Static;
internal static readonly ReflectionUtility Instance =
#if CPP
new Il2CppReflection();
#else
new ReflectionUtility();
#endif
static ReflectionUtility()
{
SetupTypeCache();
}
#region Type cache
/// Key: Type.FullName
public static readonly SortedDictionary AllTypes = new SortedDictionary(StringComparer.OrdinalIgnoreCase);
private static readonly List allTypeNames = new List();
private static void SetupTypeCache()
{
foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
CacheTypes(asm);
allTypeNames.Sort();
AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoaded;
}
private static void AssemblyLoaded(object sender, AssemblyLoadEventArgs args)
{
if (args.LoadedAssembly == null)
return;
CacheTypes(args.LoadedAssembly);
allTypeNames.Sort();
}
private static void CacheTypes(Assembly asm)
{
foreach (var type in asm.TryGetTypes())
{
if (AllTypes.ContainsKey(type.FullName))
AllTypes[type.FullName] = type;
else
{
AllTypes.Add(type.FullName, type);
allTypeNames.Add(type.FullName);
}
foreach (var key in s_cachedTypeInheritance.Keys)
{
try
{
var baseType = AllTypes[key];
if (baseType.IsAssignableFrom(type) && !s_cachedTypeInheritance[key].Contains(type))
s_cachedTypeInheritance[key].Add(type);
}
catch { }
}
}
}
#endregion
///
/// Find a in the current AppDomain whose matches the provided .
///
/// The you want to search for - case sensitive and full matches only.
/// The Type if found, otherwise null.
public static Type GetTypeByName(string fullName)
=> Instance.Internal_GetTypeByName(fullName);
internal virtual Type Internal_GetTypeByName(string fullName)
{
AllTypes.TryGetValue(fullName, out Type type);
return type;
}
// Getting the actual type of an object
internal virtual Type Internal_GetActualType(object obj)
=> obj?.GetType();
// Force-casting an object to a type
internal virtual object Internal_TryCast(object obj, Type castTo)
=> obj;
// Processing deobfuscated type names in strings
public static string ProcessTypeInString(Type type, string theString)
=> Instance.Internal_ProcessTypeInString(theString, type);
internal virtual string Internal_ProcessTypeInString(string theString, Type type)
=> theString;
// Force loading modules
public static bool LoadModule(string moduleName)
=> Instance.Internal_LoadModule(moduleName);
internal virtual bool Internal_LoadModule(string moduleName)
=> false;
public static void FindSingleton(string[] possibleNames, Type type, BindingFlags flags, List