UH4L4——调用ILRuntime中类对象属性

本章代码关键字

1
2
3
4
5
6
7
8
IType.GetMethod()                    //获取热更对象的方法信息
appDomain.Invoke() //传入要执行方法的对象,要执行的方法信息,要传入的参数,执行热更工程里的方法(属性),如果有返回值则可以接收
appDomain.BeginInvoke() //该方法配合using执行方法,需要传入方法信息,可以避免GC Alloc,性能更好
InvocationContext //appDomain.BeginInvoke方法返回的对象,通过它即可执行方法
InvocationContext.PushObject() //要执行方法的对象
InvocationContext.PushValueType<>() //传入参数
InvocationContext.Invoke() //执行方法
InvocationContext.ReadValueType<>() //获取返回值

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
namespace HotFix_Project
{
public class Lesson3_Test
{
private string str;

public Lesson3_Test() { }

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

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

调用ILRuntime中的成员属性

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

  1. 获取方法信息

    通过 IType​ 中的 GetMethod​ 方法,类似反射一样的获取对应类中的方法

    该方法除了获取属性,同样可以获取:静态方法、成员方法

    关于如何调用特定重载,详见:重载方法调用

    • 参数一:方法名(属性获取规则:get_属性名​ 为对应属性获取,set_属性名​ 为对应属性的赋值)
    • 参数二:参数数量(get​无参数,set​有一个参数)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void Start()
    {
    ILRuntimeMgr.Instance.StartILRuntime(() =>
    {
    AppDomain appDomain = ILRuntimeMgr.Instance.appDomain;
    IType type = appDomain.LoadedTypes["HotFix_Project.Lesson3_Test"];
    object obj = ((ILType)type).Instantiate(new object[] { "234" });
    print(obj);

    IMethod getStr = type.GetMethod("get_Str", 0);
    IMethod setStr = type.GetMethod("set_Str", 1);
    });
    }
  2. 调用方法

    有两种方式:

    1. 通过 appDomain.Invoke(方法名,调用对象,参数)​ 调用属性相关

      该方法除了调用属性,同样可以调用:静态方法、成员方法

      如果有多个参数,因为参数部分是变长参数,因此直接,​后继续传入即可

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      void Start()
      {
      ILRuntimeMgr.Instance.StartILRuntime(() =>
      {
      AppDomain appDomain = ILRuntimeMgr.Instance.appDomain;
      IType type = appDomain.LoadedTypes["HotFix_Project.Lesson3_Test"];
      object obj = ((ILType)type).Instantiate(new object[] { "234" });
      print(obj);

      IMethod getStr = type.GetMethod("get_Str", 0);
      IMethod setStr = type.GetMethod("set_Str", 1);

      string str = appDomain.Invoke(getStr, obj).ToString();
      print(str);
      appDomain.Invoke(setStr, obj, "设置测试");
      str = appDomain.Invoke(getStr, obj).ToString();
      print(str);
      });
      }

      输出:image

    2. 通过更节约性能的无GC Alloc(调用完后直接回收)方式调用

      该方法除了调用属性,同样可以调用:静态方法、成员方法、带 ref / out 参数方法​

      语法如下:

      1
      2
      3
      4
      5
      6
      7
      using (var method = appDomain.BeginInvoke(methodName))
      {
      method.PushObject(obj); //传入执行该方法的对象
      method.Push.....(1000); //传入指定类型参数
      method.Invoke(); //执行方法
      method.Read....() //获取指定类型返回值
      }

      使用示例

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      void Start()
      {
      ILRuntimeMgr.Instance.StartILRuntime(() =>
      {
      AppDomain appDomain = ILRuntimeMgr.Instance.appDomain;
      IType type = appDomain.LoadedTypes["HotFix_Project.Lesson3_Test"];
      object obj = ((ILType)type).Instantiate(new object[] { "234" });
      print(obj);

      IMethod getStr = type.GetMethod("get_Str", 0);
      IMethod setStr = type.GetMethod("set_Str", 1);

      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(); //执行方法
      string str = method.ReadValueType<string>(); //获取返回值
      print(str);
      }
      });
      }

      输出:image