UnityILRuntime使用UnityWebRequest加载Dll文件

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;
}
}

上一篇:编号226:翻转二叉树


下一篇:网络协议和Netty(9):Http的报文结构及一个完整Http请求的过程