转载请标明出处:http://www.cnblogs.com/zblade/

前面两篇文章从头到尾讲解了C#热更新的一些方案,从程序域来加载和卸载DLL,到使用ILRuntime来实现安卓和IOS平台的DLL热更新。文章二中讲解了ILRuntime对于IL虚拟机在加载DLL的过程中的一些解构。那么今天收尾的文章,就来讲解一下如何基于这个虚拟机实现对于类,方法,属性的调用。

一、基于appDomain来加载类实现反射的调用

对于ILRuntime中的反射,大概可以分为三种类型:一种是ILRuntime运行的DLL中,该程序集中的类之间的反射,这是基于C#的反射,应用无差别; 一种是unity游戏主工程中对DLL中类的反射,这样的反射可以分为两种,一种是获取类,然后直接调用方法, 一种是基于appDomain包装的反射,下面分别举例两种unity主工程对DLL中类的反射,来研究一下如何实现这个过程。

1、基于LoadedTypes来实现反射方法的调用

在ILRuntime中,不能基于System.Type来直接获取热更新DLL中的类,只有基于唯一的appDomain实例,基于LoadedTypes这种来获取热更新中的DLL,基于代码来分析,更为详细:

首先,加载获取该DLL中的指定类:

var it = appDomain.LoadedTypes["HotFix_Project.InstanceClass"]

跟踪LoadedTypes:

public Dictionary<string, IType> LoadedTypes{get{return mapType.InnerDictionary;}}

跟踪看mapType.InnerDictionary:

ThreadSafeDictionary<string, IType> mapType = new ThreadSafeDictionary<string, IType>();

这个mapType是什么时候装配的?

来自于文章二中的LoadAssembly的后续操作:

那么这个module.GetTypes是如何操作的?

分别基于协程来return type以及其nestedTypes,关键是看Types是怎么获取的:

关键是read操作:

继续跟进Read操作:

关键是:

var mtypes = metadata.Types

后续都是对其的封装和填充,对于metadata的填充,来自于InitializeTypeDefinitions这个操作:

关键操作是ReadType这个操作:

构建一个内部定义的类,然后做数据填充,看看关键的几个属性的设置:BaseType ,设置其父类型,fieldsrange/methods_range 是对属性范围和方法范围的设置:

所以基本方法还是ReadListRange:

在这儿,我们最终回到了文章二中对于IL虚拟机中的tableHeap的引用,最后实现了和文章二的首尾呼应。

好了,收起思绪,回到最开始的,获取类,这样获得的一个类,这样得到的一个类,继承自IType,在Unity主工程中,则需要System.Type才能继续使用反射接口,其对于的封装来自昱这个ILType封装的ReflectionType, 其中的ILRuntimeType继承自Type类:

基于其,可以直接调用System.Type的GetConstructor方法,构建实例,归并几个代码,可以表示为(直接使用的实例源代码):

var it = appDomain.LoadedTypes["HotFix_Project.InstanceClass"];
var type = it.ReflectionType;
var ctor = type.GetConstructor(new System.Type[]);
var obj = ctor.Invoke(null);

对应可以得到DLL中该类的构造函数的调用:

2、基于appDomain内嵌的Invoke来实现反射

在ILRuntime中,在appDomain中内嵌了一套Invoke的实现,可以在Unity工程中直接调用来实现对热更新DLL中类的方法的调用:

关键操作就是2步: GetType和 GetMethod,获取类型的过程,和前面有点类似,就是对mapType中存储的获取,如果没有,则进行查找和填充,这儿重点说说方法是如何获取的:

粗看就是从methods中取出来,做相应的检查,如果通过则返回,那么初始化操作看看:

最后还是从definition.Methods中取出,逐个遍历其中的方法做一个分类存储,如果有静态构造函数,且满足对于的参数条件,则执行一次静态构造。

回到开始,在获取到类和方法的相关信息后,就可以执行对于的参数检验,然后执行反射:

可见,就是获取到一个IL的解释器,然后执行相应的反射,具体Run怎么执行,就不继续深入贴图了,有兴趣的可以持续跟踪(基本思路就是对stack的操作,塞入各个参数,然后执行一次操作,塞入结果,然后退回)

对于ILRuntime的反射基本就先研究到这儿,如果要应用到自己的项目中,可以继续深入研究一下代码,看看实现的具体细节。这儿附上开源的相关文档:

ILRuntime中的反射

二、热更新DLL和Unity主工程的相互调用

基于前面的反射,我们可以基本理出热更DLL和unity主工程的交互本质: 基于IL虚拟机或者.net本身反射来实现交互,对于热更新DLL,其调用unity主工程,则主要是在热更新工程中添加对于unity工程的Assembly-CSharp的引用:

基于这个引用,可以调用其中类的各自方法,举两个类来测试:

一个不继承自MonoBehaviour:

一个继承自MonoBehaviour:

这两个Unity主工程中的类以及其中的方法,在热更新DLL中调用:

可以在Unity主工程中得到输出:

看一下track可以大概了解整个反射的执行过程。

对于Unity执行热更DLL中的调用,就是第一部分的反射实例。

总结:絮絮叨叨的写了三篇文章,算是对最近的研究做一个总结吧,现在项目还在评估这种热更新方案,基于稳妥,以及有基于slua的热更新项目用过,ILRuntime还在评估,其实本质都是相通的:基于自我实现的虚拟机(lua的虚拟机或者IL虚拟机,均基于栈实现),来构建一个自我运行环境,在里面解析执行对于的指令(lua虚拟机的指令/IL语句),来实现对热更新的代码(虽然是以资源方式热更新)。

Unity实现c#热更新方案探究(三)的更多相关文章

  1. Unity实现c#热更新方案探究(一)

    转载请标明出处:http://www.cnblogs.com/zblade/ 最近研究了一下如何在unity中实现c#的热更新,对于整个DLL热更新的过程和方案有一个初步的了解,这儿就写下来,便于后续 ...

  2. Unity实现c#热更新方案探究(二)

    转载请标明出处:http://www.cnblogs.com/zblade/ 一.IOS对DLL热更新的禁止 紧接上文,继续对C#热更新的研究.上文中,已经说了如何基于appDomain来实现对DLL ...

  3. Unity官方发布热更新方案性能对照

    孙广东  2016.3.11 Unity应用的iOS热更新 作者:丁治宇 Unity TechnologiesChina Agenda •  什么是热更新 •  为何要热更新 •  怎样在iOS 上对 ...

  4. Unity代码热更新方案 JSBinding + SharpKit 首页

    目前Unity的代码更新方案有很多,主要以lua为主. JSBinding + SharpKit 是一种新的技术,他做了两件事情: JSBinding将C#导出到 JavaScript (引擎是 Mo ...

  5. unity热更新方案对比

    Unity应用的iOS热更新 •  什么是热更新 •  为何要热更新 •  怎样在iOS 上对Unity 应用进行热更新 •  支持Unity iOS 热更新的各种Lua 插件的对照 什么是热更新 • ...

  6. Unity3D 热更新方案(集合各位专家的汇总)

    http://blog.csdn.net/guofeng526/article/details/52662994 热更新”这个词,在Unity3D的应用下,是有些语义错误的,但是作为大家都熟知的一项技 ...

  7. 腾讯开源手游热更新方案,Unity3D下的Lua编程

    原文:http://www.sohu.com/a/123334175_355140 作者|车雄生 编辑|木环 腾讯最近在开源方面的动作不断:先是微信跨平台基础组件Mars宣布开源,腾讯手游又于近期开源 ...

  8. Unity3D热更新方案网摘总结

    参考:http://blog.csdn.net/guofeng526/article/details/52662994 http://blog.csdn.net/u010019717/article/ ...

  9. 【腾讯Bugly干货分享】手游热更新方案xLua开源:Unity3D下Lua编程解决方案

    本文来自于腾讯Bugly公众号(weixinBugly),未经作者同意,请勿转载,原文地址:http://mp.weixin.qq.com/s/2bY7A6ihK9IMcA0bOFyB-Q 导语 xL ...

随机推荐

  1. 使用ACR122U NFC读卡器对M1卡进行读写操作(可以读写中文)

    因为项目需要,第一次接触到了ACR122U NFC读卡器(非接触式)和M1卡,首先介绍一下想要读写应该知道的基本知识. 我就根据我的理解先叙述一下: ACR122U 是一款连机非接触式智能卡读写器,可 ...

  2. # xrdp 在linux deploy 折腾记录

    xrdp 在linux deploy 折腾记录 1. xrdp connect fail vnc 不管用tiger or vnc4server都可以正常用,但xrdp无法连接 netstat -tnl ...

  3. ES6语法(一)

    对于ES6中的一些基础语法,包括对数组/对象/函数/字符串的操作,chroem已经支持了这些语法 // var a = '你' // console.log(a.length) let a = 'ni ...

  4. [HACK] docker runtime 挂载宿主机目录

    网上看到的很多所谓的挂载都是容器创建时期的挂载,而且参数都不清不楚,整理如下(--name别名自己加): docker run -v /src/path:/dest/path:rw ${IMAGE} ...

  5. mint17上建立lamp环境

    使用apt-get方式是最简单的也是最快捷稳定的在桌面linux环境下.   分别执行如下命令:   (1)安装MYSQL   sudo apt-get install mysql-server   ...

  6. Spring源码学习-容器BeanFactory(五) Bean的创建-探寻Bean的新生之路

    写在前面 上面四篇文章讲了Spring是如何将配置文件一步一步转化为BeanDefinition的整个流程,下面就到了正式创建Bean对象实例的环节了,我们一起继续学习吧. 2.初始化Bean对象实例 ...

  7. framework7 入门(基础布局)

    个人认为framework7是个很好的移动端框架,自带路由.下拉刷新.无限加载.时间线.各种dialog.环形图等,基本能满足大部分app的需求,可以和vue,webpack 等各种搭配. 这里讲一下 ...

  8. CRT破解版

    1.先去https://www.ttrar.com/html/VanDyke-SecureCRT.html上面下载一个CRT软件 2.下载一个注册机 http://www.ddooo.com/soft ...

  9. AI-逻辑回归函数、激活函数、损失函数

    最近开始学习人工智能,先从基本的概念学起 逻辑回归函数(预测函数):z = dot(w,x) + b 解释:假设有三个特征,即x可以表示为(x1,x2,x3),w表示权重,对应每个特征的重要程度,b表 ...

  10. 电子科技大学实验中学PK赛(一)比赛题解

    比赛来源:第十四届重庆大学程序设计大赛暨西南地区高校邀请赛现场初赛 比赛地址:http://qscoj.cn/contest/24/ A. Comb 自述 分析:统计ACM在题目描述中出现的次数,认真 ...