2021-05-07 01:22:55 +10:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace UnityExplorer
|
|
|
|
|
{
|
|
|
|
|
public static class ReflectionExtensions
|
|
|
|
|
{
|
|
|
|
|
// ReflectionUtility extensions
|
|
|
|
|
|
|
|
|
|
public static Type GetActualType(this object obj)
|
|
|
|
|
=> ReflectionUtility.Instance.Internal_GetActualType(obj);
|
|
|
|
|
|
|
|
|
|
public static object TryCast(this object obj)
|
|
|
|
|
=> ReflectionUtility.Instance.Internal_TryCast(obj, ReflectionUtility.Instance.Internal_GetActualType(obj));
|
|
|
|
|
|
|
|
|
|
public static object TryCast(this object obj, Type castTo)
|
|
|
|
|
=> ReflectionUtility.Instance.Internal_TryCast(obj, castTo);
|
|
|
|
|
|
|
|
|
|
public static T TryCast<T>(this object obj)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return (T)ReflectionUtility.Instance.Internal_TryCast(obj, typeof(T));
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
return default;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static HashSet<Type> GetImplementationsOf(this Type baseType, bool allowAbstract, bool allowGeneric)
|
|
|
|
|
=> ReflectionUtility.GetImplementationsOf(baseType, allowAbstract, allowGeneric);
|
|
|
|
|
|
|
|
|
|
// ------- Misc extensions --------
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Safely try to get all Types inside an Assembly.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static IEnumerable<Type> TryGetTypes(this Assembly asm)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return asm.GetTypes();
|
|
|
|
|
}
|
|
|
|
|
catch (ReflectionTypeLoadException e)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
return asm.GetExportedTypes();
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
return e.Types.Where(t => t != null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
return Enumerable.Empty<Type>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Check if the two objects are reference-equal, including checking for UnityEngine.Object-equality and Il2CppSystem.Object-equality.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static bool ReferenceEqual(this object objA, object objB)
|
|
|
|
|
{
|
|
|
|
|
if (object.ReferenceEquals(objA, objB))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (objA is UnityEngine.Object unityA && objB is UnityEngine.Object unityB)
|
|
|
|
|
{
|
|
|
|
|
if (unityA && unityB && unityA.m_CachedPtr == unityB.m_CachedPtr)
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if CPP
|
|
|
|
|
if (objA is Il2CppSystem.Object cppA && objB is Il2CppSystem.Object cppB
|
|
|
|
|
&& cppA.Pointer == cppB.Pointer)
|
|
|
|
|
return true;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Helper to display a simple "{ExceptionType}: {Message}" of the exception, and optionally use the inner-most exception.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public static string ReflectionExToString(this Exception e, bool innerMost = true)
|
|
|
|
|
{
|
|
|
|
|
if (innerMost)
|
2021-05-09 02:22:03 +10:00
|
|
|
|
e = e.GetInnerMostException();
|
2021-05-07 01:22:55 +10:00
|
|
|
|
|
2021-05-09 01:25:26 +10:00
|
|
|
|
return $"{e.GetType()}: {e.Message}";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Exception GetInnerMostException(this Exception e)
|
|
|
|
|
{
|
2021-06-11 17:36:35 +10:00
|
|
|
|
while (e != null)
|
2021-05-09 01:25:26 +10:00
|
|
|
|
{
|
2021-06-11 18:12:14 +10:00
|
|
|
|
if (e.InnerException == null)
|
|
|
|
|
break;
|
2021-05-09 01:25:26 +10:00
|
|
|
|
#if CPP
|
2021-06-11 18:12:14 +10:00
|
|
|
|
if (e.InnerException is System.Runtime.CompilerServices.RuntimeWrappedException)
|
2021-05-09 01:25:26 +10:00
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
e = e.InnerException;
|
2021-05-07 01:22:55 +10:00
|
|
|
|
}
|
|
|
|
|
|
2021-05-09 01:25:26 +10:00
|
|
|
|
return e;
|
2021-05-07 01:22:55 +10:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|