CLR重定向 — ILRuntime (ourpalm.github.io)

在热更流程中,主工程创建不了热更工程的类,但是如果我们使用Activator.CreateInstance来尝试创建热更工程的类的实例时,会发现是成功的,这是因为ILRuntime在内部实现了CLR重定向

CLR重定向的原理就是:在运行时先找到主工程内对应方法,然后再进行挟持(或者说使用钩子)来改变这个方法实际的调用效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static StackObject* CreateInstance(ILIntepreter intp, StackObject* esp, List<object> mStack, CLRMethod method, bool isNewObj)
{
//获取泛型参数<T>的实际类型
IType[] genericArguments = method.GenericArguments;
if (genericArguments != null && genericArguments.Length == 1)
{
var t = genericArguments[0];
if (t is ILType)//如果T是热更DLL里的类型
{
//通过ILRuntime的接口来创建实例
return ILIntepreter.PushObject(esp, mStack, ((ILType)t).Instantiate());
}
else
return ILIntepreter.PushObject(esp, mStack, Activator.CreateInstance(t.TypeForCLR));//通过系统反射接口创建实例
}
else
throw new EntryPointNotFoundException();
}

注册CreateInstance的方法,也就是说使用RegisterCLRMethodRedirection来对原方法Activator.CreateInstance进行挟持。

1
2
3
4
5
6
7
8
foreach (var i in typeof(System.Activator).GetMethods())
{
//找到名字为CreateInstance,并且是泛型方法的方法定义
if (i.Name == "CreateInstance" && i.IsGenericMethodDefinition)
{
appdomain.RegisterCLRMethodRedirection(i, CreateInstance);
}
}

在上面的官方文档中还提供了UnityEngine.Debug.Log的重定向,用于显示这个方法在热更dll中的调用堆栈。根据实际开发需要添加即可。