转载请标明出处: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. winform datagridview在添加全选checkbox时提示:不能设置 selected 或 selected 既不是表 Table 的 DataColumn 也不是 DataRelation。

    在项目中,需要多选功能,于是在datagridview添加了一列DataGridViewCheckBoxColumn 在给datagridview绑定完数据集之后,对全选进行操作的时候,发现总报错,报 ...

  2. C语言中数组使用负数值的标记

    ·引 对数组的认知 在c语言中,我们经常使用的一个结构便是数组,在最开始学习数组的时候,它被描述成这样(以一维二维数组为例):一维数组是若干个数连续排列在一起的集合,我们可以通过0-N的标记(N为数组 ...

  3. margin相关属性值

    1.图片与文字对齐问题 图片与文字默认是居底对齐.一般img标签打头的小图标与文字对齐的话,通过 img{margin:0 3px -3px 0;} 这个的东西,能实现效果和兼容性俱佳的对齐效果: d ...

  4. nginx配置前端代理

    #user nobody;worker_processes 1; #error_log logs/error.log;#error_log logs/error.log notice;#error_l ...

  5. 机器学习——KNN算法(k近邻算法)

    一 KNN算法 1. KNN算法简介 KNN(K-Nearest Neighbor)工作原理:存在一个样本数据集合,也称为训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分 ...

  6. vue - 新建一个项目

    首先: 要先安装node 及 npm Node.js官方安装包及源码下载地址:http://nodejs.org/ 双击安装,在安装界面一直Next 直到Finish完成安装. 打开控制命令行程序(C ...

  7. springmvc的日期类型转换

      springmvc的日期类型转换 # spring mvc绑定参数之类型转换有三种方式: ## 1.实体类中加日期格式化注解 @DateTimeFormat(pattern="yyyy- ...

  8. 【react】---17新增的生命周期

    一.废除的生命周期 官网文档指出使用这些生命周期的代码会在未来版本的react中更容易产生bug,尤其是对于异步渲染的版本 由于未来采用异步渲染机制,所以即将在17版本中去掉的生命周期钩子函数 com ...

  9. react-native 常用的一些插件

    react-native 常用的一些插件 最近在做react-native的app,用到的一些好用的插件,在这儿记录一下 由于返回的后台内容是富文本编辑器Quill,返回的的是Delta对象,使用了q ...

  10. 算法与数据结构(八) AOV网的关键路径(Swift版)

    上篇博客我们介绍了AOV网的拓扑序列,请参考<数据结构(七) AOV网的拓扑排序(Swift面向对象版)>.拓扑序列中包括项目的每个结点,沿着拓扑序列将项目进行下去是肯定可以将项目完成的, ...