启动HotFix

  1. 使用AppDomain加载热更程序集dll及pdb(正式发布时请将PDB去掉)
  2. 初始化ILRuntime,(设置ILRuntime主线程的线程ID ,监听调试端口等),然后做一些ILRuntime的注册
  3. 使用热更

调用Invocation

//1.通过AppDomain调用方法
//参数:类型全名(命名空间+类型)、方法名、实例、实参列表
appdomain.Invoke("XX.XXX", "XXXX", null, null);//2.通过IMethod调用方法
//预先获得IMethod,可以减低每次调用查找方法耗用的时间
IType type = appdomain.LoadedTypes["XX.XXX"];
//根据方法名称和参数个数获取方法
IMethod method = type.GetMethod("XXXX", 1);
//使用IMethod调用(参数:IMethod、实例、实参列表)
appdomain.Invoke(method, null, 123);//3.通过无GC Alloc方式调用方法
//无GC Alloc方式参数压入顺序:先将带ref/out关键字的形参参数按顺序压入初始值->若为成员方法压入this->按形参顺序压入实参
using (var ctx = appdomain.BeginInvoke(method))
{//将参数进行压栈ctx.PushInteger(123);//调用ctx.Invoke();
}//4.指定参数类型来获得IMethod
IType intType = appdomain.GetType(typeof(int));
//参数类型列表
List<IType> paramList = new List<ILRuntime.CLR.TypeSystem.IType>();
paramList.Add(intType);
//根据方法名称和参数类型列表获取方法(也可加入泛型参数类型列表获取泛型方法)
method = type.GetMethod("XXXX", paramList, null);
appdomain.Invoke(method, null, 456);//5.调用成员方法
//实例化(参数:类型全名、构造参数)
object obj = appdomain.Instantiate("XX.XXX", new object[] { 233 });
//通过ILType实例化
object obj2 = ((ILType)type).Instantiate();
//调用成员方法(属性器Get方法)
method = type.GetMethod("get_XXXXX", 0);
using (var ctx = appdomain.BeginInvoke(method))
{//将对象压栈后调用ctx.PushObject(obj);ctx.Invoke();//获取返回值int id = ctx.ReadInteger();
}
using (var ctx = appdomain.BeginInvoke(method))
{//将对象压栈后调用ctx.PushObject(obj2);ctx.Invoke();//获取返回值int id = ctx.ReadInteger();
}//6.调用泛型方法
IType stringType = appdomain.GetType(typeof(string));
IType[] genericArguments = new IType[] { stringType };
//参数:类型全名(命名空间+类型)、方法名、泛型参数类型列表、实例、实参列表
appdomain.InvokeGenericMethod("XX.XXX", "XXXX", genericArguments, null, "TestString");//7.获取泛型方法的IMethod
paramList.Clear();
paramList.Add(intType);
genericArguments = new IType[] { intType };
//根据参数类型列表及泛型参数类型列表来获取对应IMthod
method = type.GetMethod("XXXX", paramList, genericArguments);
appdomain.Invoke(method, null, 33333);//8.通过无GC Alloc方式调用带Ref/Out参数的方法
//被调用方法:public void RefOutMethod(int addition, out List<int> lst, ref int val)
method = type.GetMethod("RefOutMethod", 3);
int initialVal = 500;
using(var ctx = appdomain.BeginInvoke(method))
{//第一个ref/out参数初始值ctx.PushObject(null);//第二个ref/out参数初始值ctx.PushInteger(initialVal);//压入thisctx.PushObject(obj);//压入参数1:additionctx.PushInteger(100);//压入参数2: lst,由于是ref/out,需要压引用,这里是引用0号位,也就是第一个PushObject的位置ctx.PushReference(0);//压入参数3,val,同ref/outctx.PushReference(1);ctx.Invoke();//读取0号位的值List<int> lst = ctx.ReadObject<List<int>>(0);initialVal = ctx.ReadInteger(1);
}

委托Delegate

在ILRuntime中,若需要跨域调用委托,则需要注册适配器。
使用Action或者Func当作委托类型可以避免写转换器,但需要注册参数搭配。
完全在热更DLL内部使用的委托,直接可用,不需要做任何处理

//注册委托参数搭配
appdomain.DelegateManager.RegisterMethodDelegate<int>();
appdomain.DelegateManager.RegisterFunctionDelegate<int, string>();

如需要注册适配器,则在注册参数代码后注册转换器,将Action或者Func转换成目标委托类型即可。

//注册适配转换器
appdomain.DelegateManager.RegisterDelegateConvertor<UnityEngine.Events.UnityAction<float>>((action) =>
{return new UnityEngine.Events.UnityAction<float>((a) =>{((System.Action<float>)action)(a);});
});

继承Inheritance

跨域继承需要生成适配器,并且在ILRuntime初始化完成后进行注册。

//参数为所需跨域继承类型的适配器实例
appdomain.RegisterCrossBindingAdaptor(new XXXAdapter());

在自己实现的ILRuntime.Moudle中添加了跨域继承类型的配置功能。

CLR重定向CLRRedirection

当我们需要挟持原方法实现,添加一些热更DLL中的特殊处理的时候,就需要CLR重定向了。

//获取参数类型符合要求的MethodInfo
var mi = typeof(Debug).GetMethod("Log", new System.Type[] { typeof(object) });
//参数:要重定向的方法的MethodInfo、重定向到的方法
appdomain.RegisterCLRMethodRedirection(mi, Log_11);

CLR绑定CLRBinding

默认情况下,从热更DLL里调用Unity主工程的方法,是通过反射的方式调用的,这个过程中会产生GC Alloc,并且执行效率会偏低。
ILRuntime通过CLR方法绑定机制,可以选择性的对经常使用的CLR接口进行直接调用,从而尽可能的消除反射调用开销以及额外的GC Alloc。

//在生成CLRBinding代码后,在ILRuntime CLR重定向注册之后调用以下方法,即可使用CLR绑定
ILRuntime.Runtime.Generated.CLRBindings.Initialize(appDomain);

协程Coroutine

使用Couroutine时,C#编译器会自动生成一个实现了IEnumerator,IEnumerator,IDisposable接口的类,因为这是跨域继承,所以需要写CrossBindAdapter。
跨域继承只能有1个Adapter,因此应该尽量避免一个类同时实现多个外部接口,对于coroutine来说是IEnumerator,IEnumerator和IDisposable。
ILRuntime虽然支持,但是一定要小心这种用法,使用不当很容易造成不可预期的问题。
日常开发如果需要实现多个DLL外部接口,请在Unity这边先做一个基类实现那些个接口,然后继承那个基类。

使用了插件作者的CoroutineAdapter,尝试了以下,可以在热更dll内随意使用协程,但是CoroutineAdapter无法进行CLR绑定。

MonoBehaviour

在热更DLL里面使用MonoBehaviour是可以做到的。
需要在MonoBehaviourAdaptor中实现对应的事件方法。
为了在热更DLL里正常使用AddComponent和GetComponent需要重定向这两个方法。
也可以实现通过MonoBehaviourAdaptor在Unity获取到热更dll类型。

反射Reflection

C#工程中反射是一个非常经常用到功能,ILRuntime也对反射进行了支持,在热更DLL中使用反射跟原生C#没有任何区别。
在Unity中使用AppDomain获取DLL中类型后,使用IType的ReflectionType可获取热更DLL内的真正类型,之后正常使用反射调用方法,字段,属性即可。

序列化LitJson

非常简单的序列化反序列化,但是对LitJson源码是需要进行处理的。这里插件作者已经整理好了。

值类型绑定ValueTypeBinding

值类型绑定内部对值类型的操作进行了重定向。

ILRuntimeDemo理解相关推荐

  1. 通用解题法——回溯算法(理解+练习)

    积累算法经验,积累解题方法--回溯算法,你必须要掌握的解题方法! 什么是回溯算法呢? 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就&quo ...

  2. stream流对象的理解及使用

    我的理解:用stream流式处理数据,将数据用一个一个方法去 . (点,即调用) 得到新的数据结果,可以一步达成. 有多种方式生成 Stream Source: 从 Collection 和数组 Co ...

  3. Linux shell 学习笔记(11)— 理解输入和输出(标准输入、输出、错误以及临时重定向和永久重定向)

    1. 理解输入和输出 1.1 标准文件描述符 Linux 系统将每个对象当作文件处理.这包括输入和输出进程.Linux 用文件描述符(file descriptor)来标识每个文件对象.文件描述符是一 ...

  4. java局部变量全局变量,实例变量的理解

    java局部变量全局变量,实例变量的理解 局部变量 可以理解为写在方法中的变量. public class Variable {//类变量static String name = "小明&q ...

  5. 智能文档理解:通用文档预训练模型

    预训练模型到底是什么,它是如何被应用在产品里,未来又有哪些机会和挑战? 预训练模型把迁移学习很好地用起来了,让我们感到眼前一亮.这和小孩子读书一样,一开始语文.数学.化学都学,读书.网上游戏等,在脑子 ...

  6. 熵,交叉熵,散度理解较为清晰

    20210511 https://blog.csdn.net/qq_35455503/article/details/105714287 交叉熵和散度 自己给自己编码肯定是最小的 其他的编码都会比这个 ...

  7. mapreduce理解_大数据

    map:对不同的数据进行同种操作 reduce:按keys 把数据规约到一起 看这篇文章请出去跑两圈,然后泡一壶茶,边喝茶,边看,看完你就对hadoop 与MapReduce的整体有所了解了. [前言 ...

  8. 文件句柄和文件描述符的区别和理解指针

    句柄是Windows用来标识被应用程序所建立或使用的对象的唯一整数,Windows使用各种各样的句柄标识诸如应用程序实例,窗口,控制,位图,GDI对象等等.Windows句柄有点象C语言中的文件句柄. ...

  9. 通俗理解条件熵-数学

    就是决策树里面选划分属性用到的计算 条件熵越小表示划分之后各个集合越纯净 前面我们总结了信息熵的概念通俗理解信息熵 - 知乎专栏,这次我们来理解一下条件熵. 我们首先知道信息熵是考虑该随机变量的所有可 ...

最新文章

  1. 自己封装的一个java图片验证码
  2. VTK:Filtering之GenericClip
  3. Cairngorm初学者入门教程 第六节--Cairngorm中Command利用Delegate与Service连接
  4. Facebook大公开:解决NLG模型落地难题!工业界的新一波春天?
  5. python与h5结合实例_使用h5py合并所有h5文件
  6. 别人要访问我的电脑上部署的tomcat,必须关闭防火墙吗?
  7. 修改服务器编码和oracle编码,修改oracle 数据服务器编码
  8. wsimport的使用
  9. c语言 文本放大,Javascript 编写的文字放大效果_js
  10. python裂缝检测_通过opencv-python检测裂缝
  11. 基于matlab七轴可伸缩关节机械臂物品抓取
  12. VCC、 VDD、VSS、VEE 电压符号的解释
  13. python 写入csv时添加表头,这个是亲测,最详细最傻瓜教程
  14. 我们的爱、相约在下辈子。这辈子、记得忘了我、(看完我哭了、一定要看)
  15. 标签打印软件如何设置打印区域
  16. RK3399 Android7.1使用网络连接ADB
  17. PL/SQL Developer配置使用说明
  18. 数据库-差集交集并集
  19. 关于智慧团建忘记密码的解决方法
  20. Windows--UEFI引导安装Win10

热门文章

  1. html图片与div有空隙,html 如何将div 里面的图片设置与div等宽,没有缝隙?
  2. FTX US与IEX合作,共同搭建一个受监管、负责任和透明的市场结构
  3. 华为鸿蒙智能手表最新款,不止鸿蒙OS和智能手表,华为宣布华为Mate Pad Pro将于6月2日发布...
  4. ElementPlus的Collapse 折叠面板问题
  5. 深度学习实战之MINIST数据集
  6. 墨言教育摄影技能干货分享|为什么说云南是春天旅游必去的地方
  7. Java 通过Request请求获取IP地址
  8. 投影仪连续播放PPT的设置
  9. linux实现git免密登录
  10. 最深情的告白——郁金香(Python实现)