ILRuntime study notes (2) - the mutual call between the main project and the hot update project

Mutual call between the main project and the hot update project

1. The method of calling hot update in the main project

1. Using AppDomian, directly use the string name to call

1.1 Call the parameterless static method
appdomain.Invoke("class name", "method name", object reference [if it is a static method, it is null, and the non-static method passes the object object], parameter list); main project
:

appdomain.Invoke("HotFix_Project.InstanceClass", "StaticFunTest", null, null);

Hot update project:

        public static void StaticFunTest()
        {
    
    
            UnityEngine.Debug.Log("!!! InstanceClass.StaticFunTest()");
        }

1.2 Calling a parameterless method

Main project:

        object obj = appdomain.Instantiate("HotFix_Project.InstanceClass", new object[] {
    
     233 });
        appdomain.Invoke("HotFix_Project.InstanceClass", "FunTest", obj, null);

Hot update project:

        public void FunTest()
        {
    
    
            UnityEngine.Debug.Log("!!! InstanceClass.FunTest()");
        }

1.3 Call static method with parameters
Main project:

        appdomain.Invoke("HotFix_Project.InstanceClass", "StaticFunTest2", null, 123);

Hot update project:

        public static void StaticFunTest2(int a)
        {
    
    
            UnityEngine.Debug.Log("!!! InstanceClass.StaticFunTest2(), a=" + a);
        }

1.4 Call the method with parameters
Main project:


        object obj = appdomain.Instantiate("HotFix_Project.InstanceClass");
        appdomain.Invoke("HotFix_Project.InstanceClass", "FunTest2", obj, 22);

Hot update project:

        public void FunTest2(int a)
        {
    
    
            UnityEngine.Debug.Log("!!! InstanceClass.FunTest2(),a=" + a);
        }

1.5 Instantiate the class in the hot update

1.5.1 Instantiate classes with no-argument constructors in hot updates

        object obj = appdomain.Instantiate("HotFix_Project.InstanceClass");

or

        //预先获得IMethod,可以减低每次调用查找方法耗用的时间
        IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
        object obj = ((ILType)type).Instantiate();

1.5.2 Instantiate classes with parameterized constructors


        object obj = appdomain.Instantiate("HotFix_Project.InstanceClass",new object[] {
    
     123 });

or

        IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
        object obj = ((ILType)type).Instantiate(new object[] {
    
     321 });

2. Get the IMethod and then call it

Obtain IMethod in advance, which can reduce the time spent on each call to find the method

2.1 Static methods with parameters

        IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
        IMethod method = type.GetMethod("StaticFunTest2", 1);
        appdomain.Invoke(method, null, 123);

2.2 Non-static methods with parameters

        IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
        object obj = appdomain.Instantiate("HotFix_Project.InstanceClass", new object[] {
    
     123 });
        IMethod method = type.GetMethod("FunTest2", 1);
        appdomain.Invoke(method, obj, 222);

3. Call method without GC Alloc

        IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
        object obj = appdomain.Instantiate("HotFix_Project.InstanceClass", new object[] {
    
     123 });
        IMethod method = type.GetMethod("FunTest2", 1);
        using (var ctx = appdomain.BeginInvoke(method))
        {
    
    
            ctx.PushObject(obj);
            ctx.PushInteger(223);
            ctx.Invoke();
        }

4. Call the member method

        IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
        object obj = appdomain.Instantiate("HotFix_Project.InstanceClass", new object[] {
    
     233 });
        IMethod method = type.GetMethod("get_ID", 0);
        using (var ctx = appdomain.BeginInvoke(method))
        {
    
    
            ctx.PushObject(obj);
            ctx.Invoke();
            int id = ctx.ReadInteger();
            Debug.Log("!! HotFix_Project.InstanceClass.ID = " + id);
        }

The ReadInteger() here reads the return value return id

5. Generic method calls

5.1 Call generic method
Main project:

        IType stringType = appdomain.GetType(typeof(string));
        IType[] genericArguments = new IType[] {
    
     stringType };
        appdomain.InvokeGenericMethod("HotFix_Project.InstanceClass", "GenericMethod", genericArguments, null, "TestString");

Hot update project:

        public static void GenericMethod<T>(T a)
        {
    
    
            UnityEngine.Debug.Log("!!! InstanceClass.GenericMethod(), a=" + a);
        }

5.2 Get the IMethod of the generic method

        IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
        //参数类型列表
        List<IType> paramList = new List<ILRuntime.CLR.TypeSystem.IType>();
        IType intType = appdomain.GetType(typeof(int));
        IType stringType = appdomain.GetType(typeof(string));
        IType[] genericArguments = new IType[] {
    
     stringType };
        paramList.Add(intType);
        genericArguments = new IType[] {
    
     intType };
        IMethod method = type.GetMethod("GenericMethod", paramList, genericArguments);
        //appdomain.Invoke(method, null, 33333);
        using(var ctx = appdomain.BeginInvoke(method))
        {
    
    
            ctx.PushInteger(22333);
            ctx.Invoke();
        }

6. Ref/Out method call

        IType type = appdomain.LoadedTypes["HotFix_Project.InstanceClass"];
        IMethod method = type.GetMethod("RefOutMethod", 3);
        object obj = appdomain.Instantiate("HotFix_Project.InstanceClass", new object[] {
    
     345 });
        int initialVal = 500;
        using (var ctx = appdomain.BeginInvoke(method))
        {
    
    
            //第一个ref/out参数初始值
            ctx.PushObject(null);
            //第二个ref/out参数初始值
            ctx.PushInteger(initialVal);
            //压入this
            ctx.PushObject(obj);
            //压入参数1:addition
            ctx.PushInteger(100);
            //压入参数2: lst,由于是ref/out,需要压引用,这里是引用0号位,也就是第一个PushObject的位置
            ctx.PushReference(0);
            //压入参数3,val,同ref/out
            ctx.PushReference(1);
            ctx.Invoke();
            //读取0号位的值
            List<int> lst = ctx.ReadObject<List<int>>(0);
            initialVal = ctx.ReadInteger(1);

            Debug.Log(string.Format("lst[0]={0}, initialVal={1}", lst[0], initialVal));
        }

2. Call the method of the main project in the hot update

1. Reference the corresponding DLL

Assembly-CSharp.dll All scripts we wrote under Asset
UnityEngine.CoremMdule, etc.
Location: /Applications/unityHub/2019.4.31f1c1/Unity.app/Contents/Managed/UnityEngine/xx x.dll

2. Call directly

reference, and then you can directly call

3. Pay attention to the protection level of the type and method

Guess you like

Origin blog.csdn.net/weixin_45724919/article/details/129451964