/// <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));
        }
Exemple #2
0
        /// <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);
        }
Exemple #4
0
        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);
        }
Exemple #6
0
        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);
        }
Exemple #8
0
        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);
            }
        }