使用流程

我们可能需要热更工程去继承Unity工程中的类,那么我们就需要为其写一个适配器,具体流程如下:

  1. 新建Unity工程父类
public abstract class TestClassBase
{public virtual int Value{get{return 0;}set{}}public virtual void TestVirtual(string str){Debug.Log("!! TestClassBase.TestVirtual, str = " + str);}public abstract void TestAbstract(int gg);
}

2.编写Unity工程如口主类,并实例初始化热更新ILRuntime的AppDomain,同时加载热更新dll和pdb。

 IEnumerator LoadHotFixAssembly(){//首先实例化ILRuntime的AppDomain,AppDomain是一个应用程序域,每个AppDomain都是一个独立的沙盒appdomain = new ILRuntime.Runtime.Enviorment.AppDomain();//正常项目中应该是自行从其他地方下载dll,或者打包在AssetBundle中读取,平时开发以及为了演示方便直接从StreammingAssets中读取,//正式发布的时候需要大家自行从其他地方读取dll//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!//这个DLL文件是直接编译HotFix_Project.sln生成的,已经在项目中设置好输出目录为StreamingAssets,在VS里直接编译即可生成到对应目录,无需手动拷贝//工程目录在Assets\Samples\ILRuntime\1.6\Demo\HotFix_Project~
#if UNITY_ANDROIDWWW www = new WWW(Application.streamingAssetsPath + "/HotFix_Project.dll");
#elseWWW www = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.dll");
#endifwhile (!www.isDone)yield return null;if (!string.IsNullOrEmpty(www.error))UnityEngine.Debug.LogError(www.error);byte[] dll = www.bytes;www.Dispose();//PDB文件是调试数据库,如需要在日志中显示报错的行号,则必须提供PDB文件,不过由于会额外耗用内存,正式发布时请将PDB去掉,下面LoadAssembly的时候pdb传null即可
#if UNITY_ANDROIDwww = new WWW(Application.streamingAssetsPath + "/HotFix_Project.pdb");
#elsewww = new WWW("file:///" + Application.streamingAssetsPath + "/HotFix_Project.pdb");
#endifwhile (!www.isDone)yield return null;if (!string.IsNullOrEmpty(www.error))UnityEngine.Debug.LogError(www.error);byte[] pdb = www.bytes;fs = new MemoryStream(dll);p = new MemoryStream(pdb);try{appdomain.LoadAssembly(fs, p, new ILRuntime.Mono.Cecil.Pdb.PdbReaderProvider());}catch{Debug.LogError("加载热更DLL失败,请确保已经通过VS打开Assets/Samples/ILRuntime/1.6/Demo/HotFix_Project/HotFix_Project.sln编译过热更DLL");}
#if DEBUG && (UNITY_EDITOR || UNITY_ANDROID || UNITY_IPHONE)//由于Unity的Profiler接口只允许在主线程使用,为了避免出异常,需要告诉ILRuntime主线程的线程ID才能正确将函数运行耗时报告给Profilerappdomain.UnityMainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
#endifOnHotFixLoaded();}
  1. 入口类中调用dll继承TestClassBase的类和方法
void OnHotFixLoaded(){Debug.Log("首先我们来创建热更里的类实例");TestClassBase obj;Debug.Log("现在我们来注册适配器, 该适配器由ILRuntime/Generate Cross Binding Adapter菜单命令自动生成");//因为跨域继承必须要注册适配器。 如果是热更DLL里面继承热更里面的类型,不需要任何注册。appdomain.RegisterCrossBindingAdaptor(new TestClassBaseAdapter());Debug.Log("现在再来尝试创建一个实例");obj = appdomain.Instantiate<TestClassBase>("HotFix_Project.TestInheritance");Debug.Log("现在来调用成员方法");obj.TestAbstract(123);obj.TestVirtual("Hello");obj.Value = 233;Debug.LogFormat("obj.Value={0}", obj.Value);Debug.Log("现在换个方式创建实例");obj = appdomain.Invoke("HotFix_Project.TestInheritance", "NewObject", null, null) as TestClassBase;obj.TestAbstract(456);obj.TestVirtual("Foobar");obj.Value = 2333333;Debug.LogFormat("obj.Value={0}", obj.Value);}
  1. 生成适配器
    由于跨域继承特殊性太多,自动生成无法实现完全无副作用生成,点击ILRuntime/Generate Cross Binding Adapter菜单命令自动生成的也只是个初始模版,简化大家工作,具体代码需求还是得自己调整
using System;
using ILRuntime.CLR.Method;
using ILRuntime.Runtime.Enviorment;
using ILRuntime.Runtime.Intepreter;namespace ILRuntimeDemo
{   public class TestClassBaseAdapter : CrossBindingAdaptor{//定义访问方法的方法信息static CrossBindingFunctionInfo<System.Int32> mget_Value_0 = new CrossBindingFunctionInfo<System.Int32>("get_Value");static CrossBindingMethodInfo<System.Int32> mset_Value_1 = new CrossBindingMethodInfo<System.Int32>("set_Value");static CrossBindingMethodInfo<System.String> mTestVirtual_2 = new CrossBindingMethodInfo<System.String>("TestVirtual");static CrossBindingMethodInfo<System.Int32> mTestAbstract_3 = new CrossBindingMethodInfo<System.Int32>("TestAbstract");public override Type BaseCLRType{get{return typeof(global::TestClassBase);//这里是你想继承的类型}}public override Type AdaptorType{get{return typeof(Adapter);}}public override object CreateCLRInstance(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance){return new Adapter(appdomain, instance);}public class Adapter : global::TestClassBase, CrossBindingAdaptorType{ILTypeInstance instance;ILRuntime.Runtime.Enviorment.AppDomain appdomain;//必须要提供一个无参数的构造函数public Adapter(){}public Adapter(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance){this.appdomain = appdomain;this.instance = instance;}public ILTypeInstance ILInstance { get { return instance; } }//下面将所有虚函数都重载一遍,并中转到热更内public override void TestVirtual(System.String str){if (mTestVirtual_2.CheckShouldInvokeBase(this.instance))base.TestVirtual(str);elsemTestVirtual_2.Invoke(this.instance, str);}public override void TestAbstract(System.Int32 gg){mTestAbstract_3.Invoke(this.instance, gg);}public override System.Int32 Value{get{if (mget_Value_0.CheckShouldInvokeBase(this.instance))return base.Value;elsereturn mget_Value_0.Invoke(this.instance);}set{if (mset_Value_1.CheckShouldInvokeBase(this.instance))base.Value = value;elsemset_Value_1.Invoke(this.instance, value);}}public override string ToString(){IMethod m = appdomain.ObjectType.GetMethod("ToString", 0);m = instance.Type.GetVirtualMethod(m);if (m == null || m is ILMethod){return instance.ToString();}elsereturn instance.Type.FullName;}}}
}
  1. 热更工程中的继承实现类
using System;
using System.Collections.Generic;namespace HotFix_Project
{//一定要特别注意,:后面只允许有1个Unity主工程的类或者接口,但是可以有随便多少个热更DLL中的接口public class TestInheritance : TestClassBase{public override int Value { get; set; }public override void TestAbstract(int gg){UnityEngine.Debug.Log("!! TestInheritance.TestAbstract gg =" + gg);}public override void TestVirtual(string str){base.TestVirtual(str);UnityEngine.Debug.Log("!! TestInheritance.TestVirtual str =" + str);}public static TestInheritance NewObject(){return new HotFix_Project.TestInheritance();}}
}

ILRuntime入门05 类继承相关推荐

  1. Java面向对象编程入门练习:Manager类继承Employee类并实现求得员工平均业绩

    Java面向对象编程入门练习:Manager类继承Employee类并实现求得员工平均业绩 请定义一个Manager类,该类继承Employee类,并定义两个变量及一个构造方法,两个变量:depart ...

  2. python入门笔记——类和对象⑤(继承)

    python入门笔记--类和对象⑤(继承) # python中展现面向对象的三大特征:封装.继承.多态 # 封装:把内容封装到某个地方以便后续的使用 # 对封装来说,其实就是使用初始化构造方法将内容封 ...

  3. c++入门(类和对象and继承for系统时间显示)

    文件名:<1> time.h :<2> time.cpp :<3> CurrTime.h :<4> CurrTime.cpp :<5> ma ...

  4. python中类的继承关系使用什么符号_Python 入门 之 类的三大关系(依赖 / 组合/ 继承关系)...

    在面向对象的中,类与类之间存在三种关系:依赖关系.组合关系.继承关系. 1.依赖关系:将一个类的类名或对象当做参数传递给另一个函数被使用的关系就是依赖关系 class People: def __in ...

  5. Python|装饰器|执行时间|递归|动态属性|静态方法和类|继承和多态|isinstance类型判断|溢出|“魔法”方法|语言基础50课:学习记录(6)-函数的高级应用、面向对象编程、进阶及应用

    文章目录 系列目录 原项目地址: 第16课:函数的高级应用 装饰器(记录执行时间的例子) 递归调用 简单的总结 第17课:面向对象编程入门 类和对象 定义类 创建和使用对象 初始化方法 打印对象 面向 ...

  6. Python面向对象编程:类继承和其衍生术语

    Python面向对象编程03:类继承和其衍生术语 前面我们讲到过正则表达式字符等,上一篇分享了面向对象编程和类的结构,最后稍微提到了继承. Python面向对象编程:深度认识类class_ Pytho ...

  7. 【C++入门】C++ 继承和派生

    C++继承和派生 文章目录 C++继承和派生 一.继承和派生的概念 1.继承的概念 2.派生类 3.继承实例程序 二.类之间的两种关系 1.继承关系 2.复合关系 三.派生类覆盖基类成员&类的 ...

  8. 什么是继承?Java中如何声明一个类继承另一个类?

    在现实生活中,说到继承,多会想到子女继承父辈的财产.事业等.在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关联体系.例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动 ...

  9. C++中类成员和类继承的private、protected和public关键字作用

    摘要 C++中类成员和类继承的private.protected和public关键字作用. 类成员中,private.protected和public 类成员变量或函数前加上关键字private.pr ...

最新文章

  1. C++的多个有序链表合并
  2. 力扣算法题—045跳跃游戏二
  3. 【图解分布式架构】看不懂直接面壁
  4. java tts引擎_让Java说话-用Java实现语音引擎
  5. Linux系统各文件、目录介绍
  6. 为什么你的数据库经常会被破防呢?原因原来是这——Sql注入问题(源码+文字深度解析)
  7. JavaEE学习12--JDBC(上)
  8. FeedingBottle 3.2另一个无线破解GUI
  9. comsol积分函数_空间与时间的积分方法概述
  10. bigmp4.com AI 视频无损放大高清补帧工具
  11. web前端之跳一跳网页版小游戏
  12. IB书单推荐:没有所谓的“闲书”
  13. 【Json转换为实体类】
  14. 课堂笔记(常用软件,网站资源)
  15. linux测试读写的工具,Linux 下的硬盘读写速度测试工具
  16. Games101,作业7(多线程提速)
  17. 企业微信客户端开启开发者模式
  18. Apache 配置------FastCGI方式使用PHP(包含:linux下编译安装fmod_fcgid,配置apache以支持FastCGI)
  19. win7下运行Excel2007,出现“向程序发送命令时出现问题”的解决
  20. acw - 4262.空调

热门文章

  1. Loser应该知道的6个残酷人生事实(血泪翻译)
  2. 利用OpenCV的函数mean()和meanStdDev()计算图像的均值和标准差
  3. 观念什么意思_理念是什么意思(观念和理念的区别)
  4. 手把手教你在64位Win7下部署16位汇编学习环境
  5. 基于51单片机实现闹钟功能
  6. delegate、传值、跳转页面
  7. TradPlus SDK - IOS接入心得
  8. iOS 8支持高保真音乐
  9. linux防火墙的设置
  10. 划分亚洲国家的三个足球梯队