using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ILRuntime.Runtime.Enviorment;
using UnityEngine.Networking;
using ILRuntime.CLR.TypeSystem;
using ILRuntime.CLR.Method;
public class InstanceDebug : MonoBehaviour
{
using System.Collections; using System.Collections.Generic; using UnityEngine; using ILRuntime.Runtime.Enviorment; using UnityEngine.Networking; using ILRuntime.CLR.TypeSystem; using ILRuntime.CLR.Method; public class InstanceDebug : MonoBehaviour { AppDomain m_AppDomain; System.IO.MemoryStream fs; System.IO.MemoryStream p; byte[] dll = null; byte[] pdb = null; private void Start() { StartCoroutine(LoadHotFixAssembly()); } private IEnumerator LoadHotFixAssembly() { m_AppDomain = new AppDomain(); UnityWebRequest request = new UnityWebRequest("file:///" + Application.streamingAssetsPath + "/MyHotfix.dll"); DownloadHandlerBuffer downloadHandler = new DownloadHandlerBuffer(); request.downloadHandler = downloadHandler; yield return request.SendWebRequest(); if(request.result == UnityWebRequest.Result.ConnectionError || !request.isDone || request.result == UnityWebRequest.Result.DataProcessingError) { Debug.Log("读取失败" + request.error); } else { Debug.Log("读取成功"); //dll = request.downloadHandler.data; dll = request.downloadHandler.data; request.Dispose(); } request = new UnityWebRequest("file:///" + Application.streamingAssetsPath + "/MyHotfix.pdb"); DownloadHandlerBuffer downloadHandler1 = new DownloadHandlerBuffer(); request.downloadHandler = downloadHandler1; yield return request.SendWebRequest(); if (request.result == UnityWebRequest.Result.ConnectionError || !request.isDone || request.result == UnityWebRequest.Result.DataProcessingError) { Debug.Log("读取失败" + request.error); } else { Debug.Log("读取成功"); pdb = request.downloadHandler.data; } if (dll != null && pdb != null) { fs = new System.IO.MemoryStream(dll); p = new System.IO.MemoryStream(pdb); try { m_AppDomain.LoadAssembly(fs, p, new ILRuntime.Mono.Cecil.Pdb.PdbReaderProvider()); InitializeILRuntime(); OnHotFixLoaded(); } catch (System.Exception e) { Debug.Log("热更失败" + e); } } else { Debug.Log("dll或pdb未读取成功"); } } private void InitializeILRuntime() { //告诉ILRuntime主线程ID才能正确将函数运行耗时报告给profiler(因为Unity的Profiler接口只允许再主线程中使用 #if DEBUG && (UNITY_EDITOR || UNITY_ANDROID || UNITY_IPHONE) m_AppDomain.UnityMainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId; #endif //这里做一些ILRuntime的注册 } private void OnHotFixLoaded() { Debug.Log("First"); m_AppDomain.Invoke("MyHotfix.InstanceClass", "StaticFunTest", null, null); Debug.Log("调用静态带参方法"); m_AppDomain.Invoke("MyHotfix.InstanceClass", "StaticFunTest2", null, 111); Debug.Log("通过IMethod调用方法"); IType type = m_AppDomain.LoadedTypes["MyHotfix.InstanceClass"]; IMethod method = type.GetMethod("StaticFunTest2", 1); m_AppDomain.Invoke(method, null, 222); Debug.Log("通过无GC Alloc方式调用方法"); using (var ctx = m_AppDomain.BeginInvoke(method)) { ctx.PushInteger(123456); ctx.Invoke(); } Debug.Log("指定参数类型来获得IMethod"); IType intType = m_AppDomain.GetType(typeof(int)); //参数类型列表 List<IType> paramList = new List<IType>(); paramList.Add(intType); method = type.GetMethod("StaticFunTest2", paramList, null); m_AppDomain.Invoke(method, null, 3333); Debug.Log("实例化热更里的类"); object obj = m_AppDomain.Instantiate("MyHotfix.InstanceClass", new object[] { 233 }); //第二种方式 object obj2 = ((ILType)type).Instantiate(); Debug.Log("调用成员方法"); method = type.GetMethod("get_ID", 0); using (var ctx = m_AppDomain.BeginInvoke(method)) { ctx.PushObject(obj); ctx.Invoke(); int id = ctx.ReadInteger(); Debug.Log("ID是:" + id); } using (var ctx = m_AppDomain.BeginInvoke(method)) { ctx.PushObject(obj2); ctx.Invoke(); int id = ctx.ReadInteger(); Debug.Log("ID是 : " + id); } Debug.Log("调用泛型方法"); IType stringType = m_AppDomain.GetType(typeof(string)); IType[] genericArguments = new IType[] { stringType }; m_AppDomain.InvokeGenericMethod("MyHotfix.InstanceClass", "GenericMethod", genericArguments, null, "TestString这是我的泛型方法的参数"); Debug.Log("获取泛型方法的IMethod"); paramList.Clear(); paramList.Add(intType); genericArguments = new IType[] { intType }; method = type.GetMethod("GenericMethod", paramList, genericArguments); m_AppDomain.Invoke(method, null, "asdasdfadf"); Debug.Log("调用带有ref/out参数的方法"); method = type.GetMethod("RefoutMethod", 3); int initialVal = 500; using (var ctx = m_AppDomain.BeginInvoke(method)) { //第一个ref/out参数初始值 ctx.PushObject(null); //第二个ref/out参数初始值 ctx.PushInteger(initialVal); //压入this ctx.PushObject(obj); //压入参数addition ctx.PushInteger(100); //压入参数2: lst,由于是ref/out,需要压引用,这里是引用0号位,也就是第一个PushObject的位置 ctx.PushReference(0); ctx.PushReference(1); ctx.Invoke(); List<int> list = ctx.ReadObject<List<int>>(0); initialVal = ctx.ReadInteger(1); Debug.Log(string.Format("list[0] = {0}, initialVal = {1}", list[0], initialVal)); } } private void OnDestroy() { if (fs != null) { fs.Close(); } if (p != null) { p.Close(); } fs = null; p = null; } }
AppDomain m_AppDomain;
System.IO.MemoryStream fs;
System.IO.MemoryStream p;
byte[] dll = null;
byte[] pdb = null;
private void Start()
{
StartCoroutine(LoadHotFixAssembly());
}
private IEnumerator LoadHotFixAssembly()
{
m_AppDomain = new AppDomain();
UnityWebRequest request = new UnityWebRequest("file:///" + Application.streamingAssetsPath + "/MyHotfix.dll");
DownloadHandlerBuffer downloadHandler = new DownloadHandlerBuffer();
request.downloadHandler = downloadHandler;
yield return request.SendWebRequest();
if(request.result == UnityWebRequest.Result.ConnectionError || !request.isDone || request.result == UnityWebRequest.Result.DataProcessingError)
{
Debug.Log("读取失败" + request.error);
}
else
{
Debug.Log("读取成功");
//dll = request.downloadHandler.data;
dll = request.downloadHandler.data;
request.Dispose();
}
request = new UnityWebRequest("file:///" + Application.streamingAssetsPath + "/MyHotfix.pdb");
DownloadHandlerBuffer downloadHandler1 = new DownloadHandlerBuffer();
request.downloadHandler = downloadHandler1;
yield return request.SendWebRequest();
if (request.result == UnityWebRequest.Result.ConnectionError || !request.isDone || request.result == UnityWebRequest.Result.DataProcessingError)
{
Debug.Log("读取失败" + request.error);
}
else
{
Debug.Log("读取成功");
pdb = request.downloadHandler.data;
}
if (dll != null && pdb != null)
{
fs = new System.IO.MemoryStream(dll);
p = new System.IO.MemoryStream(pdb);
try
{
m_AppDomain.LoadAssembly(fs, p, new ILRuntime.Mono.Cecil.Pdb.PdbReaderProvider());
InitializeILRuntime();
OnHotFixLoaded();
}
catch (System.Exception e)
{
Debug.Log("热更失败" + e);
}
}
else
{
Debug.Log("dll或pdb未读取成功");
}
}
private void InitializeILRuntime()
{
//告诉ILRuntime主线程ID才能正确将函数运行耗时报告给profiler(因为Unity的Profiler接口只允许再主线程中使用
#if DEBUG && (UNITY_EDITOR || UNITY_ANDROID || UNITY_IPHONE)
m_AppDomain.UnityMainThreadID = System.Threading.Thread.CurrentThread.ManagedThreadId;
#endif
//这里做一些ILRuntime的注册
}
private void OnHotFixLoaded()
{
Debug.Log("First");
m_AppDomain.Invoke("MyHotfix.InstanceClass", "StaticFunTest", null, null);
Debug.Log("调用静态带参方法");
m_AppDomain.Invoke("MyHotfix.InstanceClass", "StaticFunTest2", null, 111);
Debug.Log("通过IMethod调用方法");
IType type = m_AppDomain.LoadedTypes["MyHotfix.InstanceClass"];
IMethod method = type.GetMethod("StaticFunTest2", 1);
m_AppDomain.Invoke(method, null, 222);
Debug.Log("通过无GC Alloc方式调用方法");
using (var ctx = m_AppDomain.BeginInvoke(method))
{
ctx.PushInteger(123456);
ctx.Invoke();
}
Debug.Log("指定参数类型来获得IMethod");
IType intType = m_AppDomain.GetType(typeof(int));
//参数类型列表
List<IType> paramList = new List<IType>();
paramList.Add(intType);
method = type.GetMethod("StaticFunTest2", paramList, null);
m_AppDomain.Invoke(method, null, 3333);
Debug.Log("实例化热更里的类");
object obj = m_AppDomain.Instantiate("MyHotfix.InstanceClass", new object[] { 233 });
//第二种方式
object obj2 = ((ILType)type).Instantiate();
Debug.Log("调用成员方法");
method = type.GetMethod("get_ID", 0);
using (var ctx = m_AppDomain.BeginInvoke(method))
{
ctx.PushObject(obj);
ctx.Invoke();
int id = ctx.ReadInteger();
Debug.Log("ID是:" + id);
}
using (var ctx = m_AppDomain.BeginInvoke(method))
{
ctx.PushObject(obj2);
ctx.Invoke();
int id = ctx.ReadInteger();
Debug.Log("ID是 : " + id);
}
Debug.Log("调用泛型方法");
IType stringType = m_AppDomain.GetType(typeof(string));
IType[] genericArguments = new IType[] { stringType };
m_AppDomain.InvokeGenericMethod("MyHotfix.InstanceClass", "GenericMethod", genericArguments, null, "TestString这是我的泛型方法的参数");
Debug.Log("获取泛型方法的IMethod");
paramList.Clear();
paramList.Add(intType);
genericArguments = new IType[] { intType };
method = type.GetMethod("GenericMethod", paramList, genericArguments);
m_AppDomain.Invoke(method, null, "asdasdfadf");
Debug.Log("调用带有ref/out参数的方法");
method = type.GetMethod("RefoutMethod", 3);
int initialVal = 500;
using (var ctx = m_AppDomain.BeginInvoke(method))
{
//第一个ref/out参数初始值
ctx.PushObject(null);
//第二个ref/out参数初始值
ctx.PushInteger(initialVal);
//压入this
ctx.PushObject(obj);
//压入参数addition
ctx.PushInteger(100);
//压入参数2: lst,由于是ref/out,需要压引用,这里是引用0号位,也就是第一个PushObject的位置
ctx.PushReference(0);
ctx.PushReference(1);
ctx.Invoke();
List<int> list = ctx.ReadObject<List<int>>(0);
initialVal = ctx.ReadInteger(1);
Debug.Log(string.Format("list[0] = {0}, initialVal = {1}", list[0], initialVal));
}
}
private void OnDestroy()
{
if (fs != null)
{
fs.Close();
}
if (p != null)
{
p.Close();
}
fs = null;
p = null;
}
}