在ILRuntime中可能会需要继承协程,所以我们需要自己写一个协程适配器。

在ILRuntime文件夹内新建一个Adaptor文件夹,并在其中新建CoroutineAdaptor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using ILRuntime.CLR.Method;
using ILRuntime.Runtime.Enviorment;
using ILRuntime.Runtime.Intepreter;
using System.Collections;
using System.Collections.Generic;


public class CoroutineAdaptor : CrossBindingAdaptor
{
static CrossBindingFunctionInfo<object> m_Current = new CrossBindingFunctionInfo<object>("Current");

public override System.Type BaseCLRType => null;

public override System.Type AdaptorType => typeof(Adaptor);

public override System.Type[] BaseCLRTypes => new System.Type[] {typeof(IEnumerator<object>) , typeof(IEnumerator) , typeof(System.IDisposable)};

public override object CreateCLRInstance(AppDomain appdomain, ILTypeInstance instance)
{
return new Adaptor(appdomain,instance);
}
public class Adaptor : IEnumerator<object>, System.IDisposable, IEnumerator, CrossBindingAdaptorType
{
private AppDomain m_AppDomain;
private ILTypeInstance m_ILTypeInstance;
private IMethod m_GetCurrent;
private IMethod m_DisposeMethod;
private IMethod m_MoveNextMethod;
private IMethod m_ResetMethod;
private IMethod m_ToStringMethod;
public Adaptor() { }//必须有无参构造函数
public Adaptor(AppDomain appDomain,ILTypeInstance instance)
{
m_AppDomain = appDomain;
m_ILTypeInstance = instance;
}
public ILTypeInstance ILInstance
{
get
{
return m_ILTypeInstance;
}
}

public object Current
{
get
{
if (m_GetCurrent == null)
{
m_GetCurrent = m_ILTypeInstance.Type.GetMethod("get_Current",0);
if(m_GetCurrent == null)//有可能在ILTypeInstance里面取不到,这时候从System.Collections.IEnumerator里面取
{
m_GetCurrent = m_ILTypeInstance.Type.GetMethod("System.Collections.IEnumerator.get_Current",0);
}
}
if (m_GetCurrent != null)
{
object result = m_AppDomain.Invoke(m_GetCurrent, m_ILTypeInstance,null);
return result;
}
else
{
return null;
}
}
}


public void Dispose()
{
if (m_DisposeMethod != null)
{
m_AppDomain.Invoke(m_DisposeMethod,m_ILTypeInstance,null);
}
else
{
m_DisposeMethod = m_ILTypeInstance.Type.GetMethod("Dispose", 0);
if(m_DisposeMethod == null)//有可能在ILTypeInstance里面取不到,这时候从System.IDisposable里面取
{
m_DisposeMethod = m_ILTypeInstance.Type.GetMethod("System.IDisposable.Dispose", 0);
}
}
}

public bool MoveNext()
{
if (m_MoveNextMethod == null)
{
m_MoveNextMethod = m_ILTypeInstance.Type.GetMethod("MoveNext", 0);
}
if (m_MoveNextMethod != null)
{
bool result = (bool)m_AppDomain.Invoke(m_MoveNextMethod,m_ILTypeInstance,null);
return result;
}
else
{
return false;
}
}

public void Reset()
{
if (m_ResetMethod != null)
{
m_AppDomain.Invoke(m_ResetMethod,m_ILTypeInstance,null);
}
else
{
m_ResetMethod = m_ILTypeInstance.Type.GetMethod ("Reset", 0);
}
}
public override string ToString()
{
if (m_ToStringMethod == null)
{
m_ToStringMethod = m_AppDomain.ObjectType.GetMethod("ToString", 0);//基础Object通过这种方式获取方法
}
IMethod m = m_ILTypeInstance.Type.GetVirtualMethod(m_ToStringMethod);
if (m != null || m is ILMethod)//检测ToString方法是否被热更类重载过
{
return m_ILTypeInstance.ToString();
}
else
{
return m_ILTypeInstance.Type.FullName;
}

}
}
}

协程适配器注册

先在ILRuntimeCLRBinding中注册

1
2
3
4
5
6
static void InitILRuntime(AppDomain domain)
{
domain.RegisterCrossBindingAdaptor(new InheritanceAdaptor());
domain.RegisterCrossBindingAdaptor(new CoroutineAdaptor());
}

点击ILRuntime/Generate CLR Binding Code by Analysis重新生成绑定文件

然后再在ILRuntimeManager里面注册

1
2
3
4
5
6
7
8
9
10
void InitializeILRuntime()
{
//...

//跨域继承绑定类注册
m_AppDomain.RegisterCrossBindingAdaptor(new InheritanceAdaptor());
m_AppDomain.RegisterCrossBindingAdaptor(new CoroutineAdaptor());//+++
//CLR绑定初始化
ILRuntime.Runtime.Generated.CLRBindings.Initialize(m_AppDomain);
}

协程测试

在HotFix工程中添加TestCoroutine文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using UnityEngine;

namespace HotFix
{
public class TestCoroutine
{
public static void RunTest()
{
GameStart.Instance.StartCoroutine(MyCoroutine());
}
static System.Collections.IEnumerator MyCoroutine()
{
Debug.Log("协程开始:" + Time.time);
yield return new WaitForSeconds(2);
Debug.Log("协程结束" + Time.time);
}
}
}

然后再在ILRuntimeManagerOnHotFixLoaded中执行

1
2
3
4
void OnHotFixLoaded()
{
m_AppDomain.Invoke("HotFix.TestCoroutine","RunTest",null,null);
}