/// <summary> /// Attempt to cast the object to the provided type. /// </summary> /// <param name="obj">The object you want to cast.</param> /// <param name="castTo">The Type you want to cast to.</param> /// <returns>The object, as the type (or a normal C# object) if successful or the input value if not.</returns> public static object Il2CppCast(this object obj, Type castTo) { if (!(obj is Il2CppSystem.Object ilObj)) { return(obj); } if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr)) { return(obj); } IntPtr castFromPtr = il2cpp_object_get_class(ilObj.Pointer); if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr)) { return(obj); } if (RuntimeSpecificsStore.IsInjected(castToPtr)) { return(UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(ilObj.Pointer)); } return(Activator.CreateInstance(castTo, ilObj.Pointer)); }
/// <summary> /// Version of TryCast without the generic restriction /// </summary> private static bool TryCast <T>(Il2CppObjectBase obj, out T t) { t = default; var nativeClassPtr = Il2CppClassPointerStore <T> .NativeClassPtr; if (nativeClassPtr == IntPtr.Zero) { MelonLogger.Warning($"{typeof(T)} is not an Il2Cpp reference type"); return(false); } var num = IL2CPP.il2cpp_object_get_class(obj.Pointer); if (!IL2CPP.il2cpp_class_is_assignable_from(nativeClassPtr, num)) { MelonLogger.Warning($"{obj.GetType()} is not a {typeof(T)}"); return(false); } if (RuntimeSpecificsStore.IsInjected(num)) { t = (T)ClassInjectorBase.GetMonoObjectFromIl2CppPointer(obj.Pointer); return(true); } var type = Il2CppClassPointerStore <T> .CreatedTypeRedirect; if ((object)type == null) { type = typeof(T); } t = (T)Activator.CreateInstance(type, obj.Pointer); return(true); }
public static Type GetActualType(this object obj) { if (obj == null) { return(null); } var type = obj.GetType(); #if CPP if (obj is Il2CppSystem.Object ilObject) { if (ilObject is CppType) { return(typeof(CppType)); } if (!string.IsNullOrEmpty(type.Namespace)) { // Il2CppSystem-namespace objects should just return GetType, // because using GetIl2CppType returns the System namespace type instead. if (type.Namespace.StartsWith("System.") || type.Namespace.StartsWith("Il2CppSystem.")) { return(ilObject.GetType()); } } var il2cppType = ilObject.GetIl2CppType(); // check if type is injected IntPtr classPtr = il2cpp_object_get_class(ilObject.Pointer); if (RuntimeSpecificsStore.IsInjected(classPtr)) { var typeByName = GetTypeByName(il2cppType.FullName); if (typeByName != null) { return(typeByName); } } // this should be fine for all other il2cpp objects var getType = GetMonoType(il2cppType); if (getType != null) { return(getType); } } #endif return(type); }
public override Type GetActualType(object obj) { if (obj == null) { return(null); } var type = obj.GetType(); if (obj is Il2CppSystem.Object cppObject) { // weird specific case - if the object is an Il2CppSystem.Type, then return so manually. if (cppObject is CppType) { return(typeof(CppType)); } if (!string.IsNullOrEmpty(type.Namespace)) { // Il2CppSystem-namespace objects should just return GetType, // because using GetIl2CppType returns the System namespace type instead. if (type.Namespace.StartsWith("System.") || type.Namespace.StartsWith("Il2CppSystem.")) { return(cppObject.GetType()); } } var cppType = cppObject.GetIl2CppType(); // check if type is injected IntPtr classPtr = il2cpp_object_get_class(cppObject.Pointer); if (RuntimeSpecificsStore.IsInjected(classPtr)) { var typeByName = ReflectionUtility.GetTypeByName(cppType.FullName); if (typeByName != null) { return(typeByName); } } // this should be fine for all other il2cpp objects var getType = GetMonoType(cppType); if (getType != null) { return(getType); } } return(type); }
internal override Type Internal_GetActualType(object obj) { if (obj == null) { return(null); } var type = obj.GetType(); try { if (IsString(obj)) { return(typeof(string)); } if (IsIl2CppPrimitive(type)) { return(il2cppPrimitivesToMono[type.FullName]); } if (obj is Il2CppSystem.Object cppObject) { var cppType = cppObject.GetIl2CppType(); // check if type is injected IntPtr classPtr = il2cpp_object_get_class(cppObject.Pointer); if (RuntimeSpecificsStore.IsInjected(classPtr)) { // Note: This will fail on injected subclasses. // - {Namespace}.{Class}.{Subclass} would be {Namespace}.{Subclass} when injected. // Not sure on solution yet. return(GetTypeByName(cppType.FullName) ?? type); } if (AllTypes.TryGetValue(cppType.FullName, out Type primitive) && primitive.IsPrimitive) { return(primitive); } return(GetUnhollowedType(cppType) ?? type); } } catch (Exception ex) { ExplorerCore.LogWarning("Exception in IL2CPP GetActualType: " + ex); } return(type); }
public static object Il2CppCast(object obj, Type castTo) { if (!(obj is Il2CppSystem.Object ilObj)) { return(obj); } if (!typeof(Il2CppSystem.Object).IsAssignableFrom(castTo)) { return(obj as System.Object); } IntPtr castToPtr; if (!ClassPointers.ContainsKey(castTo)) { castToPtr = (IntPtr)typeof(Il2CppClassPointerStore <>) .MakeGenericType(new Type[] { castTo }) .GetField("NativeClassPtr", BF.Public | BF.Static) .GetValue(null); ClassPointers.Add(castTo, castToPtr); } else { castToPtr = ClassPointers[castTo]; } if (castToPtr == IntPtr.Zero) { return(obj); } var classPtr = il2cpp_object_get_class(ilObj.Pointer); if (!il2cpp_class_is_assignable_from(castToPtr, classPtr)) { return(obj); } if (RuntimeSpecificsStore.IsInjected(castToPtr)) { return(UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(ilObj.Pointer)); } return(Activator.CreateInstance(castTo, ilObj.Pointer)); }
/// <summary> /// WARNING: Pubternal API (internal). Do not use. May change during any update. /// </summary> /// <typeparam name="TObject"></typeparam> /// <param name="obj"></param> /// <param name="castedObject"></param> /// <returns></returns> public static bool TryCastTo <TObject>(this object obj, out TObject castedObject) { if (obj is TObject c) { castedObject = c; return(true); } #if IL2CPP if (obj is Il2CppObjectBase il2cppObject) { IntPtr nativeClassPtr = Il2CppClassPointerStore <TObject> .NativeClassPtr; if (nativeClassPtr == IntPtr.Zero) { throw new ArgumentException($"{typeof( TObject )} is not an Il2Cpp reference type"); } var instancePointer = il2cppObject.Pointer; IntPtr intPtr = IL2CPP.il2cpp_object_get_class(instancePointer); if (!IL2CPP.il2cpp_class_is_assignable_from(nativeClassPtr, intPtr)) { castedObject = default; return(false); } if (RuntimeSpecificsStore.IsInjected(intPtr)) { castedObject = (TObject)UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(instancePointer); return(castedObject != null); } castedObject = Il2CppUtilities.Factory <TObject> .CreateProxyComponent(instancePointer); return(castedObject != null); } #endif castedObject = default; return(false); }
public static bool Is <T>(this Il2CppObjectBase obj) { var nestedTypeClassPointer = Il2CppClassPointerStore <T> .NativeClassPtr; if (nestedTypeClassPointer == IntPtr.Zero) { throw new ArgumentException($"{typeof(T)} is not an Il2Cpp reference type"); } var ownClass = IL2CPP.il2cpp_object_get_class(obj.Pointer); if (!IL2CPP.il2cpp_class_is_assignable_from(nestedTypeClassPointer, ownClass)) { return(false); } if (RuntimeSpecificsStore.IsInjected(ownClass)) { return(ClassInjectorBase.GetMonoObjectFromIl2CppPointer(obj.Pointer) is T); } return(true); }
public bool IsInjectedType(Type type) { IntPtr ptr = GetClassPointerForType(type); return(ptr != IntPtr.Zero && RuntimeSpecificsStore.IsInjected(ptr)); }
internal override object Internal_TryCast(object obj, Type castTo) { if (obj == null) { return(null); } var type = obj.GetType(); if (type == castTo) { return(obj); } // from structs if (type.IsValueType) { // from il2cpp primitive to system primitive if (IsIl2CppPrimitive(type) && castTo.IsPrimitive) { return(MakeMonoPrimitive(obj)); } // from system primitive to il2cpp primitive else if (IsIl2CppPrimitive(castTo)) { return(MakeIl2CppPrimitive(castTo, obj)); } // from other structs to il2cpp object else if (typeof(Il2CppSystem.Object).IsAssignableFrom(castTo)) { return(BoxIl2CppObject(obj)); } else { return(obj); } } // from string to il2cpp.Object / il2cpp.String if (obj is string && typeof(Il2CppSystem.Object).IsAssignableFrom(castTo)) { return(BoxStringToType(obj, castTo)); } // from il2cpp objects... if (!(obj is Il2CppObjectBase cppObj)) { return(obj); } // from Il2CppSystem.Object to a struct if (castTo.IsValueType) { return(UnboxCppObject(cppObj, castTo)); } // or to system string else if (castTo == typeof(string)) { return(UnboxString(obj)); } if (!Il2CppTypeNotNull(castTo, out IntPtr castToPtr)) { return(obj); } // Casting from il2cpp object to il2cpp object... IntPtr castFromPtr = il2cpp_object_get_class(cppObj.Pointer); if (!il2cpp_class_is_assignable_from(castToPtr, castFromPtr)) { return(null); } if (RuntimeSpecificsStore.IsInjected(castToPtr)) { var injectedObj = UnhollowerBaseLib.Runtime.ClassInjectorBase.GetMonoObjectFromIl2CppPointer(cppObj.Pointer); return(injectedObj ?? obj); } try { return(Activator.CreateInstance(castTo, cppObj.Pointer)); } catch { return(obj); } }