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中的成员属性基本方法概述
获取方法信息
- 通过
IType
中的GetMethod
方法,类似反射一样的获取对应类中的方法。 - 规则:
get_属性名
为对应属性获取。set_属性名
为对应属性的赋值。
- 通过
调用方法
- 有两种方式:
- 通过
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
}
});
总结
- ILRuntime不能直接获取、修改热更工程中对象的成员变量,需要用成员属性封装一次。
- ILRuntime中获取属性的get和set方法规则为:
get_属性名
、set_属性名
。 - 调用属性方法有两种方式:
- 通过
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