CustomBridge没有起到作用
在测试使用示例时,我发现CustomBridge并不能达到预期的效果。下面是NewClassTest的修改:
//#define TEST
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using IFix.Core;
using System.IO;
//1、执行菜单“InjectFix/Fix”生成补丁;
//2、注释“NewBehaviourScript”,“SubSystem2”两个类,以及NewClassTest的Init函数里头new SubSystem2的那行语句;
//3、执行菜单“InjectFix/Inject”,模拟线上没有“NewBehaviourScript”,“SubSystem2”的版本;
//4、NewClassTest.cs拖到场景,运行看下效果,此时只加载SubSystem1;
//5、把生成的补丁拷贝到Resources下,再次运行看下效果;
public interface IMonoBehaviour
{
void Start();//简单demo,只定义了Start方法,实际Awake,Update,OnDestroy。。。都类似
void Update();
}
public interface ISubSystem
{
bool running { get; }
void Destroy();
void Start();
void Stop();
}
public class SubSystem1 : ISubSystem
{
public bool running { get { return true; } }
public void Start()
{
Debug.Log("SubSystem1.Start");
}
public void Stop()
{
Debug.Log("SubSystem1.Stop");
}
public void Destroy()
{
Debug.Log("SubSystem1.Destroy");
}
}
#if TEST
[IFix.Interpret]
public class NewBehaviourScript : IMonoBehaviour
{
private int tick = 0;
public void Start()
{
Debug.Log("NewBehaviourScript.Start");
}
public void Update()
{
if (tick++ % 60 == 0)
{
Debug.Log("NewBehaviourScript.Update");
}
}
}
[IFix.Interpret]
public class SubSystem2 : ISubSystem
{
public bool running { get { return true; } }
public void Start()
{
Debug.Log("SubSystem2.Start, create GameObject and attach a NewBehaviourScript");
var go = new GameObject("hehe");
var behaviour = go.AddComponent(typeof(VMBehaviourScript)) as VMBehaviourScript;
behaviour.VMMonoBehaviour = new NewBehaviourScript();
}
public void Stop()
{
Debug.Log("SubSystem2.Stop");
}
public void Destroy()
{
Debug.Log("SubSystem2.Destroy");
}
}
#endif
public class NewClassTest : MonoBehaviour
{
List<ISubSystem> subsystems = new List<ISubSystem>();
void Awake()
{
var patch = Resources.Load<TextAsset>("Assembly-CSharp.patch");
if (patch != null)
{
Debug.Log("loading Assembly-CSharp.patch ...");
var sw = System.Diagnostics.Stopwatch.StartNew();
PatchManager.Load(new MemoryStream(patch.bytes));
Debug.Log("patch Assembly-CSharp.patch, using " + sw.ElapsedMilliseconds + " ms");
}
Init();
}
[IFix.Patch]
private void Init()
{
subsystems.Add(new SubSystem1());
#if TEST
subsystems.Add(new SubSystem2());
StartCoroutine(UpdateTest());
#endif
}
#if TEST
[IFix.Interpret]
private IEnumerator UpdateTest()
{
while (true)
{
yield return new WaitForSeconds(1);
Debug.Log("11111111111111111111");
}
}
#endif
void Start()
{
foreach (var subSystem in subsystems)
{
subSystem.Start();
}
}
void OnDestroy()
{
foreach (var subSystem in subsystems)
{
subSystem.Destroy();
}
}
}
[IFix.CustomBridge]
public static class AdditionalBridge
{
static List<Type> bridge = new List<Type>()
{
typeof(ISubSystem),
typeof(IMonoBehaviour),
typeof(IEnumerator)
};
}
修改后的示例中,我增加了一个协程方法,同时在Bridge中增加了IEnumerator,但是运行加载热更文件时会报错:
KeyNotFoundException: The given key was not present in the dictionary.
System.Collections.Generic.Dictionary`2[TKey,TValue].get_Item (TKey key) (at <e1319b7195c343e79b385cd3aa43f5dc>:0)
IFix.Core.PatchManager.readSlotInfo (System.IO.BinaryReader reader, System.Collections.Generic.Dictionary`2[TKey,TValue] itfMethodToId, System.Type[] externTypes, System.Int32 maxId) (at <ba81e2664e14464ea91a7e42530565c9>:0)
IFix.Core.PatchManager.Load (System.IO.Stream stream) (at <ba81e2664e14464ea91a7e42530565c9>:0)
NewClassTest.Awake () (at <544c37ead6fa48b194169c8b57481067>:0)
新加的协程无法正常运行。
但奇怪的是如果我在原代码(Inject时的代码)中多加入另一个协程方法,就算不在CustomBridge中声明IEnumerator,patch也能正常加载并运行。
是我哪里使用的方式不正确吗?待求证并指明解决方案
如果之前有过返回 IEnumerator 类型的函数,那[IFix.Interpret]就没问题; 如果之前没有过,就得手动加个接口,把 IEnumerator<System.Object> 放到[IFix.CustomBridge]里。
如果之前有过返回 IEnumerator 类型的函数,那[IFix.Interpret]就没问题; 如果之前没有过,就得手动加个接口,把 IEnumerator<System.Object> 放到[IFix.CustomBridge]里。
我尝试过,并不能解决问题。 协程方法返回的是System.Collections.IEnumerator,而不是System.Collections.Generic.IEnumerator<out T>,并不是一个派生接口,按说在IFix.CustomBridge中加IEnumerator应该可以生效,而不用加 IEnumerator<System.Object> 。
更新下InjectFix,还是添加 IEnumerator<System.Object>
反编译看下,因为UpdateTest(),编译器生成一个类,该类实现了 IEnumerator<System.Object>,IEnumerator ,IDisposable

而IEnumerator<System.Object> 实现 IDisposable, IEnumerator ,所以即使只加该接口,另两个也会自动加入

但IEnumerator 没有实现任何接口,只添加该接口,会少东西
