5.Unity调用ILR对象属性

5.Unity调用ILRuntime-属性调用


5.1 知识点

回顾上节课知识点 复制对应代码

ILRuntimeManager.Instance.StartILRuntime(() =>
{
    // 这里面做的事情是在加载完了dll和pdb文件后做的
    ILRuntime.Runtime.Enviorment.AppDomain appDomain = ILRuntimeManager.Instance.appDomain;
    IType type = appDomain.LoadedTypes["HotFix_Project.Lesson4_Test"];
    object obj = ((ILType)type).Instantiate(new object[] { "234" });
    print(obj);
});

Unity无法跨域直接获取、修改ILRuntime中成员变量

ILRuntime中并没有提供让Unity直接获取或修改成员变量的方案。我们只能通过在ILRuntime中封装属性的形式来达到目的。

在热更工程封装属性,并且重新生成

class Lesson4_Test
{
    private string str;
    public Lesson4_Test()
    {

    }

    public Lesson4_Test(string str)
    {
        this.str = str;
    }

    public string Str
    {
        get
        {
            return str;
        }
        set
        {
            str = value;
        }
    }
}

调用ILRuntime中的成员属性方法

调用ILRuntime中的成员属性基本方法概述

  1. 获取方法信息

    • 通过 IType 中的 GetMethod 方法,类似反射一样的获取对应类中的方法。
    • 规则:
      • get_属性名 为对应属性获取。
      • set_属性名 为对应属性的赋值。
  2. 调用方法

    • 有两种方式:
      • 通过 appdomain.Invoke(方法名, 调用对象, 参数) 调用。
      • 通过更节约性能的无GC Alloc(调用完后直接回收)方式调用。
        using (var method = appDomain.BeginInvoke(methodName))
        {
              method.PushObject(obj);// 传入执行该方法的对象
              method.Push.....(1000);// 传入指定类型参数
              method.Invoke();// 执行方法
              method.Read....()// 获取指定类型返回值
        }
        

注意:每次修改热更工程后的代码,一定要重新生成。

获取成员属性方法信息并调用

ILRuntimeManager.Instance.StartILRuntime(() =>
{
    // 这里面做的事情是在加载完了dll和pdb文件后做的
    ILRuntime.Runtime.Enviorment.AppDomain appDomain = ILRuntimeManager.Instance.appDomain;
    IType type = appDomain.LoadedTypes["HotFix_Project.Lesson4_Test"];
    object obj = ((ILType)type).Instantiate(new object[] { "234" });
    print(obj); // HotFix_Project.Lesson4_Test
    
    // 获取属性
    IMethod getStr = type.GetMethod("get_Str", 0); // get不用传参数,参数为0
    IMethod setStr = type.GetMethod("set_Str", 1); // set要传一个值进行复制,参数为1
    
    // 通过 appdomain.Invoke(方法信息, 调用对象, 参数) 调用
    string str = appDomain.Invoke(getStr, obj).ToString();
    print(str); // 234
    appDomain.Invoke(setStr, obj, "666");
    str = appDomain.Invoke(getStr, obj).ToString();
    print(str); // 666
    
    // 通过更节约性能的无GC Alloc(调用完后直接回收)方式调用
    // 获取属性
    using (var method = appDomain.BeginInvoke(getStr))
    {
        method.PushObject(obj); // 传入执行该方法的对象
        method.Invoke(); // 执行方法
        str = method.ReadValueType<string>(); // method有Read其他类型的API,是其他类型调用即可
        print(str); // 666
    }
    
    // 设置属性
    using (var method = appDomain.BeginInvoke(setStr))
    {
        method.PushObject(obj); // 传入执行该方法的对象
        string tempStr = "9999";
        method.PushValueType<string>(ref tempStr);
        method.Invoke();
    }
    // 查看设置完后的打印值
    using (var method = appDomain.BeginInvoke(getStr))
    {
        method.PushObject(obj); // 传入执行该方法的对象
        method.Invoke(); // 执行方法
        str = method.ReadValueType<string>();
        print(str); // 9999
    }
});

总结

  1. ILRuntime不能直接获取、修改热更工程中对象的成员变量,需要用成员属性封装一次。
  2. ILRuntime中获取属性的get和set方法规则为:get_属性名set_属性名
  3. 调用属性方法有两种方式:
    • 通过 appdomain.Invoke(方法名, 调用对象, 参数) 调用。
    • 通过更节约性能的无GC Alloc(调用完后直接回收)方式调用,虽然写起来复杂但更加节约性能,推荐使用。

5.2 知识点代码

Lesson4_Test

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace HotFix_Project
{
    class Lesson4_Test
    {
        private string str;
        public Lesson4_Test()
        {

        }

        public Lesson4_Test(string str)
        {
            this.str = str;
        }

        public string Str
        {
            get
            {
                return str;
            }
            set
            {
                str = value;
            }
        }
    }
}

Lesson05_Unity调用ILRuntime_属性调用

using ILRuntime.CLR.Method;
using ILRuntime.CLR.TypeSystem;
using System.Collections;
using System.Collections.Generic;
using BaseFramework;
using UnityEngine;

public class Lesson05_Unity调用ILRuntime_属性调用 : MonoBehaviour
{
    void Start()
    {
        #region 知识点一 回顾上节课知识点 复制对应代码

        ILRuntimeManager.Instance.StartILRuntime(() =>
        {
            //这里面做的事情 是在加载完了dll和pdb文件后做的
            ILRuntime.Runtime.Enviorment.AppDomain appDomain = ILRuntimeManager.Instance.appDomain;
            IType type = appDomain.LoadedTypes["HotFix_Project.Lesson4_Test"];
            object obj = ((ILType)type).Instantiate(new object[] { "234" });
            print(obj);//HotFix_Project.Lesson4_Test

            
            
            // IType.GetMethod 传入xet_属性名和参数数量 得到方法信息
            //1.获取方法信息
            //  通过IType中的GetMethod方法,类似反射一样的获取对应类中的方法
            //  规则:
            // get_属性名 为对应属性获取
            // set_属性名 为对应属性的赋值
            IMethod getStr = type.GetMethod("get_Str", 0);//get不用传参数 所以参数为0
            IMethod setStr = type.GetMethod("set_Str", 1);//set要传一个值进行复制 所以参数为1

            
            
            
            
            //2.调用方法
            //  调用方法有两种方式
            
            
            // Appdomain.Invoke(方法信息,调用对象,参数)调用
            //  2-1:通过appdomain.Invoke(方法名,调用对象,参数)调用
            //去获取属性
            string str = appDomain.Invoke(getStr, obj).ToString();
            print(str);//234
            //去设置属性,如果有更多参数逐个传就行
            appDomain.Invoke(setStr, obj, "666");
            str = appDomain.Invoke(getStr, obj).ToString();
            print(str);//666

            
            
            // 通过更节约性能的无GC Alloc(调用完后直接回收)方式调用
            //  2-2:通过更节约性能的无GC Alloc(调用完后直接回收)方式调用
            //    using (var method = appDomain.BeginInvoke(methodName))
            //    {
            //          method.PushObject(obj);//传入执行该方法的对象
            //          method.Push.....(1000);//传入指定类型参数
            //          method.Invoke();//执行方法
            //          method.Read....()//获取指定类型返回值
            //    }
            
            //获取属性
            using (var method = appDomain.BeginInvoke(getStr))
            {
                method.PushObject(obj); //传入执行该方法的对象
                method.Invoke(); //执行方法
                str = method.ReadValueType<string>();//method有Read其他类型的API 是其他类型调用即可
                print(str);//666
            }

            //设置属性
            using (var method = appDomain.BeginInvoke(setStr))
            {
                method.PushObject(obj); //传入执行该方法的对象
                string tempStr = "9999";
                method.PushValueType<string>(ref tempStr);
                method.Invoke();
            }
            //查看设置完后的打印值
            using (var method = appDomain.BeginInvoke(getStr))
            {
                method.PushObject(obj); //传入执行该方法的对象
                method.Invoke(); //执行方法
                str = method.ReadValueType<string>();
                print(str);//9999
            }
        });

        #endregion

        #region 知识点二 Unity无法跨域直接获取、修改ILRuntime中成员变量

        //ILRuntime中并没有提供让Unity直接获取或修改成员变量的方案
        //我们只能通过在ILRuntime中封装属性的形式来达到目的

        #endregion

        #region 知识点三 调用ILRuntime中的成员属性方法

        //1.获取方法信息
        //  通过IType中的GetMethod方法,类似反射一样的获取对应类中的方法
        //  规则:get_属性名 为对应属性获取
        //        set_属性名 为对应属性的赋值

        //2.调用方法
        //  有两种方式
        //  2-1:通过appdomain.Invoke(方法名,调用对象,参数)调用

        //  2-2:通过更节约性能的无GC Alloc(调用完后直接回收)方式调用
        //    using (var method = appDomain.BeginInvoke(methodName))
        //    {
        //          method.PushObject(obj);//传入执行该方法的对象
        //          method.Push.....(1000);//传入指定类型参数
        //          method.Invoke();//执行方法
        //          method.Read....()//获取指定类型返回值
        //    }

        //注意:
        //每次修改热更工程后代码,一定要重新生成

        #endregion

        #region 总结

        //1.ILRuntime不能直接获取、修改热更工程中对象的成员变量,需要用成员属性封装一次
        //2.ILRuntime中获取属性的get和set方法规则为:get_属性名、set_属性名
        //3.调用属性方法有两种方式
        //  1:通过appdomain.Invoke(方法名,调用对象,参数)调用
        //  2:通过更节约性能的无GC Alloc(调用完后直接回收)方式调用
        //    using (var method = appDomain.BeginInvoke(methodName))
        //    {
        //          method.PushObject(obj);//传入执行该方法的对象
        //          method.Push.....(1000);//传入指定类型参数
        //          method.Invoke();//执行方法
        //          method.Read....()//获取指定类型返回值
        //    }
        //  其中虽然方式二写起来复杂,但是更加节约性能,推荐使用,可以尝试进行封装

        #endregion
    }
}

5.3 练习题

练习一下Unity跨域实例化ILRuntime中的类对象,并且获取、修改其中的成员属性



转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏