5
5
using System . Reflection ;
6
6
using UnityEngine ;
7
7
using BF = System . Reflection . BindingFlags ;
8
-
9
8
#if CPP
10
9
using ILType = Il2CppSystem . Type ;
11
10
using UnhollowerBaseLib ;
12
11
using UnhollowerRuntimeLib ;
12
+ using System . Runtime . InteropServices ;
13
13
#endif
14
14
15
15
namespace Explorer . Helpers
@@ -20,78 +20,68 @@ public class ReflectionHelpers
20
20
21
21
#if CPP
22
22
public static ILType GameObjectType => Il2CppType . Of < GameObject > ( ) ;
23
- public static ILType TransformType => Il2CppType . Of < Transform > ( ) ;
24
- public static ILType ObjectType => Il2CppType . Of < UnityEngine . Object > ( ) ;
25
- public static ILType ComponentType => Il2CppType . Of < Component > ( ) ;
26
- public static ILType BehaviourType => Il2CppType . Of < Behaviour > ( ) ;
23
+ public static ILType TransformType => Il2CppType . Of < Transform > ( ) ;
24
+ public static ILType ObjectType => Il2CppType . Of < UnityEngine . Object > ( ) ;
25
+ public static ILType ComponentType => Il2CppType . Of < Component > ( ) ;
26
+ public static ILType BehaviourType => Il2CppType . Of < Behaviour > ( ) ;
27
+ #else
28
+ public static Type GameObjectType => typeof ( GameObject ) ;
29
+ public static Type TransformType => typeof ( Transform ) ;
30
+ public static Type ObjectType => typeof ( UnityEngine . Object ) ;
31
+ public static Type ComponentType => typeof ( Component ) ;
32
+ public static Type BehaviourType => typeof ( Behaviour ) ;
33
+ #endif
27
34
28
- private static readonly MethodInfo tryCastMethodInfo = typeof ( Il2CppObjectBase ) . GetMethod ( "TryCast" ) ;
29
- private static readonly Dictionary < Type , MethodInfo > cachedTryCastMethods = new Dictionary < Type , MethodInfo > ( ) ;
35
+ #if CPP
36
+ private static readonly Dictionary < Type , IntPtr > ClassPointers = new Dictionary < Type , IntPtr > ( ) ;
30
37
31
38
public static object Il2CppCast ( object obj , Type castTo )
32
39
{
33
- if ( ! typeof ( Il2CppSystem . Object ) . IsAssignableFrom ( castTo ) ) return obj ;
40
+ if ( ! ( obj is Il2CppSystem . Object ilObj ) )
41
+ return obj ;
34
42
35
- if ( ! cachedTryCastMethods . ContainsKey ( castTo ) )
36
- {
37
- cachedTryCastMethods . Add ( castTo , tryCastMethodInfo . MakeGenericMethod ( castTo ) ) ;
38
- }
43
+ if ( ! typeof ( Il2CppSystem . Object ) . IsAssignableFrom ( castTo ) )
44
+ return obj ;
39
45
40
- return cachedTryCastMethods [ castTo ] . Invoke ( obj , null ) ;
41
- }
42
- #else
43
- public static Type GameObjectType => typeof ( GameObject ) ;
44
- public static Type TransformType => typeof ( Transform ) ;
45
- public static Type ObjectType => typeof ( UnityEngine . Object ) ;
46
- public static Type ComponentType => typeof ( Component ) ;
47
- public static Type BehaviourType => typeof ( Behaviour ) ;
48
- #endif
49
-
50
- public static bool IsEnumerable ( Type t )
51
- {
52
- if ( typeof ( IEnumerable ) . IsAssignableFrom ( t ) )
46
+ IntPtr castToPtr ;
47
+ if ( ! ClassPointers . ContainsKey ( castTo ) )
53
48
{
54
- return true ;
55
- }
49
+ castToPtr = ( IntPtr ) typeof ( Il2CppClassPointerStore < > )
50
+ . MakeGenericType ( new Type [ ] { castTo } )
51
+ . GetField ( "NativeClassPtr" , BF . Public | BF . Static )
52
+ . GetValue ( null ) ;
56
53
57
- #if CPP
58
- if ( t . IsGenericType && t . GetGenericTypeDefinition ( ) is Type g )
59
- {
60
- return typeof ( Il2CppSystem . Collections . Generic . List < > ) . IsAssignableFrom ( g )
61
- || typeof ( Il2CppSystem . Collections . Generic . IList < > ) . IsAssignableFrom ( g )
62
- || typeof ( Il2CppSystem . Collections . Generic . HashSet < > ) . IsAssignableFrom ( g ) ;
54
+ if ( castToPtr == IntPtr . Zero )
55
+ {
56
+ ExplorerCore . LogWarning ( $ "[Il2CppCast] Could not get an IntPtr for castTo '{ castTo . FullName } '!") ;
57
+ return obj ;
58
+ }
59
+
60
+ ClassPointers . Add ( castTo , castToPtr ) ;
63
61
}
64
62
else
65
63
{
66
- return typeof ( Il2CppSystem . Collections . IList ) . IsAssignableFrom ( t ) ;
64
+ castToPtr = ClassPointers [ castTo ] ;
67
65
}
68
- #else
69
- return false ;
70
- #endif
66
+
67
+ IntPtr objPtr = ilObj . Pointer ;
68
+ var classPtr = il2cpp_object_get_class ( objPtr ) ;
69
+
70
+ //if (RuntimeSpecificsStore.IsInjected(classPtr))
71
+ // return obj;
72
+
73
+ if ( ! il2cpp_class_is_assignable_from ( castToPtr , classPtr ) )
74
+ return obj ;
75
+
76
+ return Activator . CreateInstance ( castTo , objPtr ) ;
71
77
}
72
78
73
- public static bool IsDictionary ( Type t )
74
- {
75
- if ( typeof ( IDictionary ) . IsAssignableFrom ( t ) )
76
- {
77
- return true ;
78
- }
79
+ [ DllImport ( "GameAssembly" , CallingConvention = CallingConvention . Cdecl , CharSet = CharSet . Ansi ) ]
80
+ public static extern bool il2cpp_class_is_assignable_from ( IntPtr klass , IntPtr oklass ) ;
79
81
80
- #if CPP
81
- if ( t . IsGenericType && t . GetGenericTypeDefinition ( ) is Type g )
82
- {
83
- return typeof ( Il2CppSystem . Collections . Generic . Dictionary < , > ) . IsAssignableFrom ( g )
84
- || typeof ( Il2CppSystem . Collections . Generic . IDictionary < , > ) . IsAssignableFrom ( g ) ;
85
- }
86
- else
87
- {
88
- return typeof ( Il2CppSystem . Collections . IDictionary ) . IsAssignableFrom ( t )
89
- || typeof ( Il2CppSystem . Collections . Hashtable ) . IsAssignableFrom ( t ) ;
90
- }
91
- #else
92
- return false ;
82
+ [ DllImport ( "GameAssembly" , CallingConvention = CallingConvention . Cdecl , CharSet = CharSet . Ansi ) ]
83
+ public static extern IntPtr il2cpp_object_get_class ( IntPtr obj ) ;
93
84
#endif
94
- }
95
85
96
86
public static Type GetTypeByName ( string fullName )
97
87
{
@@ -169,48 +159,55 @@ public static bool LoadModule(string module)
169
159
return false ;
170
160
}
171
161
172
- public static string ExceptionToString ( Exception e )
162
+ public static bool IsEnumerable ( Type t )
173
163
{
164
+ if ( typeof ( IEnumerable ) . IsAssignableFrom ( t ) )
165
+ {
166
+ return true ;
167
+ }
168
+
174
169
#if CPP
175
- if ( IsFailedGeneric ( e ) )
170
+ if ( t . IsGenericType && t . GetGenericTypeDefinition ( ) is Type g )
176
171
{
177
- return "Unable to initialize this type." ;
172
+ return typeof ( Il2CppSystem . Collections . Generic . List < > ) . IsAssignableFrom ( g )
173
+ || typeof ( Il2CppSystem . Collections . Generic . IList < > ) . IsAssignableFrom ( g )
174
+ || typeof ( Il2CppSystem . Collections . Generic . HashSet < > ) . IsAssignableFrom ( g ) ;
178
175
}
179
- else if ( IsObjectCollected ( e ) )
176
+ else
180
177
{
181
- return "Garbage collected in Il2Cpp." ;
178
+ return typeof ( Il2CppSystem . Collections . IList ) . IsAssignableFrom ( t ) ;
182
179
}
180
+ #else
181
+ return false ;
183
182
#endif
184
- return e . GetType ( ) + ", " + e . Message ;
185
183
}
186
184
187
- #if CPP
188
- public static bool IsFailedGeneric ( Exception e )
185
+ public static bool IsDictionary ( Type t )
189
186
{
190
- return IsExceptionOfType ( e , typeof ( TargetInvocationException ) ) && IsExceptionOfType ( e , typeof ( TypeLoadException ) ) ;
191
- }
187
+ if ( typeof ( IDictionary ) . IsAssignableFrom ( t ) )
188
+ {
189
+ return true ;
190
+ }
192
191
193
- public static bool IsObjectCollected ( Exception e )
194
- {
195
- return IsExceptionOfType ( e , typeof ( ObjectCollectedException ) ) ;
192
+ #if CPP
193
+ if ( t . IsGenericType && t . GetGenericTypeDefinition ( ) is Type g )
194
+ {
195
+ return typeof ( Il2CppSystem . Collections . Generic . Dictionary < , > ) . IsAssignableFrom ( g )
196
+ || typeof ( Il2CppSystem . Collections . Generic . IDictionary < , > ) . IsAssignableFrom ( g ) ;
197
+ }
198
+ else
199
+ {
200
+ return typeof ( Il2CppSystem . Collections . IDictionary ) . IsAssignableFrom ( t )
201
+ || typeof ( Il2CppSystem . Collections . Hashtable ) . IsAssignableFrom ( t ) ;
202
+ }
203
+ #else
204
+ return false ;
205
+ #endif
196
206
}
197
207
198
- public static bool IsExceptionOfType ( Exception e , Type t , bool strict = true , bool checkInner = true )
208
+ public static string ExceptionToString ( Exception e )
199
209
{
200
- bool isType ;
201
-
202
- if ( strict )
203
- isType = e . GetType ( ) == t ;
204
- else
205
- isType = t . IsAssignableFrom ( e . GetType ( ) ) ;
206
-
207
- if ( isType ) return true ;
208
-
209
- if ( e . InnerException != null && checkInner )
210
- return IsExceptionOfType ( e . InnerException , t , strict ) ;
211
- else
212
- return false ;
210
+ return e . GetType ( ) + ", " + e . Message ;
213
211
}
214
- #endif
215
212
}
216
213
}
0 commit comments