using UnityEngine; using System.Collections.Generic; using ILRuntime.Other; using System; using System.Collections; using ILRuntime.Runtime.Enviorment; using ILRuntime.Runtime.Intepreter; using ILRuntime.CLR.Method; namespace ILCrossBinding { public class CoroutineAdapter : CrossBindingAdaptor { public override Type BaseCLRType { get { return null; } } public override Type[] BaseCLRTypes { get { //跨域继承只能有1个Adapter,因此应该尽量避免一个类同时实现多个外部接口,对于coroutine来说是IEnumerator,IEnumerator和IDisposable, //ILRuntime虽然支持,但是一定要小心这种用法,使用不当很容易造成不可预期的问题 //日常开发如果需要实现多个DLL外部接口,请在Unity这边先做一个基类实现那些个接口,然后继承那个基类 return new Type[] { typeof(IEnumerator), typeof(IEnumerator), typeof(IDisposable) }; } } public override Type AdaptorType { get { return typeof(Adaptor); } } public override object CreateCLRInstance(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance) { return new Adaptor(appdomain, instance); } //Coroutine生成的类实现了IEnumerator, IEnumerator, IDisposable,所以都要实现,这个可以通过reflector之类的IL反编译软件得知 internal class Adaptor : IEnumerator, IEnumerator, IDisposable, CrossBindingAdaptorType { ILTypeInstance instance; ILRuntime.Runtime.Enviorment.AppDomain appdomain; public Adaptor() { } public Adaptor(ILRuntime.Runtime.Enviorment.AppDomain appdomain, ILTypeInstance instance) { this.appdomain = appdomain; this.instance = instance; } public ILTypeInstance ILInstance { get { return instance; } } IMethod mCurrentMethod; bool mCurrentMethodGot; public object Current { get { if (!mCurrentMethodGot) { mCurrentMethod = instance.Type.GetMethod("get_Current", 0); if (mCurrentMethod == null) { //这里写System.Collections.IEnumerator.get_Current而不是直接get_Current是因为coroutine生成的类是显式实现这个接口的,通过Reflector等反编译软件可得知 //为了兼容其他只实现了单一Current属性的,所以上面先直接取了get_Current mCurrentMethod = instance.Type.GetMethod("System.Collections.IEnumerator.get_Current", 0); } mCurrentMethodGot = true; } if (mCurrentMethod != null) { var res = appdomain.Invoke(mCurrentMethod, instance, null); return res; } else { return null; } } } IMethod mDisposeMethod; bool mDisposeMethodGot; public void Dispose() { if (!mDisposeMethodGot) { mDisposeMethod = instance.Type.GetMethod("Dispose", 0); if (mDisposeMethod == null) { mDisposeMethod = instance.Type.GetMethod("System.IDisposable.Dispose", 0); } mDisposeMethodGot = true; } if (mDisposeMethod != null) { appdomain.Invoke(mDisposeMethod, instance, null); } } IMethod mMoveNextMethod; bool mMoveNextMethodGot; public bool MoveNext() { if (!mMoveNextMethodGot) { mMoveNextMethod = instance.Type.GetMethod("MoveNext", 0); mMoveNextMethodGot = true; } if (mMoveNextMethod != null) { return (bool)appdomain.Invoke(mMoveNextMethod, instance, null); } else { return false; } } IMethod mResetMethod; bool mResetMethodGot; public void Reset() { if (!mResetMethodGot) { mResetMethod = instance.Type.GetMethod("Reset", 0); mResetMethodGot = true; } if (mResetMethod != null) { appdomain.Invoke(mResetMethod, instance, null); } } public override string ToString() { IMethod m = appdomain.ObjectType.GetMethod("ToString", 0); m = instance.Type.GetVirtualMethod(m); if (m == null || m is ILMethod) { return instance.ToString(); } else return instance.Type.FullName; } } } }