# 注意事项
# 委托类型的绑定
在主工程中调用热更工程的代码时,需要绑定委托适配器和委托转换器
- 委托适配器:如果将委托实例传出给 ILRuntime 外部使用,那就意味着需要将委托实例转换成真正的 CLR(C# 运行时)委托实例,这个过程需要动态创建 CLR 的委托实例。由于 IL2CPP 之类的 AOT 编译技术无法在运行时生成新的类型,所以在创建委托实例的时候 ILRuntime 选择了显式注册的方式,以保证问题不被隐藏到上线后才发现。
同一个参数组合的委托,只需要注册一次即可,例如:
delegate void SomeDelegate(int a, float b); | |
Action<int, float> act; |
这两个委托都只需要在 ILRuntimeDelegateHelper.cs
注册一个适配器即可。 注册方法如下
appDomain.DelegateManager.RegisterMethodDelegate<int, float>(); |
如果是带返回类型的委托,例如:
delegate bool SomeFunction(int a, float b); | |
Func<int, float, bool> act; |
需要按照以下方式注册
appDomain.DelegateManager.RegisterFunctionDelegate<int, float, bool>(); |
- 委托转换器:ILRuntime 内部是使用 Action, 以及 Func 这两个系统自带委托类型来生成的委托实例,所以如果你需要将一个不是 Action 或者 Func 类型的委托实例传到 ILRuntime 外部使用的话,除了委托适配器,还需要额外写一个转换器,将 Action 和 Func 转换成你真正需要的那个委托类型。比如上面例子中的 SomeFunction 类型的委托,其所需的 Convertor 应如下实现:
appdomain.DelegateManager.RegisterDelegateConvertor<SomeFunction>((action) => | |
{ | |
return new SomeFunction((a, b) => | |
{ | |
return ((Func<int, float, bool>)action)(a, b); | |
}); | |
}); |
为了避免不必要的麻烦,以及后期热更出现问题,建议项目遵循以下几点:
- 尽量避免不必要的跨域委托调用
- 尽量使用 Action 以及 Func 这两个系统内置万用委托类型
# 无法使用的写法
以下写法会导致无法打成 dll,需注意:
- 经过测试 ref List
不宜当做参数取返回值,否则方法连调用都不能调用 - 自定义类型的二维数据使用会报错 ( Cannot find method:.ctor in type:Point2 [0...,0...], token=System.Void Point2 [0...,0...]::.ctor (System.Int32,System.Int32))
- for 层次太深在协程里也会报错,非协程还不知道。
- 结构体数组会出现在数组范围内的索引给报越界的情况,可以用 class 类数组
- LitJson 解析 List 里的类时,若类里包含枚举类型,且该枚举类型使用了 get,set,则该枚举类型在 dll 打包使用时会为空
- Linq 的列表排序会导致打包失败.
(原因是没有添加委托适配器)
unlockCardDic = unlockCardDic.OrderByDescending(o => o.Key).ToDictionary(o => o.Key, p => p.Value); |