From b9aad8367992ffbf442d72d875bf7bdd4bf8e259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?johnche=28=E8=BD=A6=E9=9B=84=E7=94=9F=29?= Date: Fri, 9 Mar 2018 17:31:11 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=9C=A8=E5=AD=90=E7=B1=BBov?= =?UTF-8?q?erride=E5=87=BD=E6=95=B0=E9=80=9A=E8=BF=87base=E8=B0=83?= =?UTF-8?q?=E7=94=A8=E7=88=B6=E7=B1=BB=E5=AE=9E=E7=8E=B0=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Assets/XLua/Doc/hotfix.md | 17 ++- Assets/XLua/Examples/08_Hotfix/HotfixTest2.cs | 29 +++++ Assets/XLua/Src/Editor/Hotfix.cs | 104 ++++++++++++++++++ Assets/XLua/Src/LuaEnv.cs | 13 +++ Tools/XLuaHotfixInject.exe | Bin 30720 -> 32768 bytes Tools/XLuaHotfixInject.pdb | Bin 52736 -> 56832 bytes 6 files changed, 161 insertions(+), 2 deletions(-) diff --git a/Assets/XLua/Doc/hotfix.md b/Assets/XLua/Doc/hotfix.md index 3dc77c8..5ba982e 100644 --- a/Assets/XLua/Doc/hotfix.md +++ b/Assets/XLua/Doc/hotfix.md @@ -29,8 +29,6 @@ Win命令行 copy UnityPath\Editor\Data\Managed\Mono.Cecil.* Project\Assets\XLua 不支持静态构造函数。 -不支持在子类override函数通过base调用父类实现。 - 目前只支持Assets下代码的热补丁,不支持引擎,c#系统库的热补丁。 ## API @@ -46,6 +44,21 @@ xlua.private_accessible(class) * 描述 : 让一个类的私有字段,属性,方法等可用 * class : 同xlua.hotfix的class参数 +base(csobj) + +* 描述 : 子类override函数通过base调用父类实现。 +* csobj : 对象 +* 返回值 : 新对象,可以通过该对象base上的方法 + +例子(位于HotfixTest2.cs): + +```lua +xlua.hotfix(CS.BaseTest, 'Foo', function(self, p) + print('BaseTest', p) + base(self):Foo(p) +end) +``` + util.hotfix_ex(class, method_name, fix) * 描述 : xlua.hotfix的增强版本,可以在fix函数里头执行原来的函数,缺点是fix的执行会略慢。 diff --git a/Assets/XLua/Examples/08_Hotfix/HotfixTest2.cs b/Assets/XLua/Examples/08_Hotfix/HotfixTest2.cs index 4d180ec..dd94778 100644 --- a/Assets/XLua/Examples/08_Hotfix/HotfixTest2.cs +++ b/Assets/XLua/Examples/08_Hotfix/HotfixTest2.cs @@ -106,6 +106,23 @@ public class InnerTypeTest } } +public class BaseTestBase +{ + public virtual void Foo(int p) + { + Debug.Log("BaseTestBase.Foo, p = " + p); + } +} + +[Hotfix] +public class BaseTest : BaseTestBase +{ + public override void Foo(int p) + { + Debug.Log("BaseTest.Foo, p = " + p); + } +} + [Hotfix] public struct StructTest { @@ -350,6 +367,18 @@ public class HotfixTest2 : MonoBehaviour { { Debug.Log("throw in lua an catch in c# ok, e.Message:" + e.Message); } + + + BaseTestBase bt = new BaseTest(); + bt.Foo(1); + + luaenv.DoString(@" + xlua.hotfix(CS.BaseTest, 'Foo', function(self, p) + print('BaseTest', p) + base(self):Foo(p) + end) + "); + bt.Foo(2); } void TestStateful() diff --git a/Assets/XLua/Src/Editor/Hotfix.cs b/Assets/XLua/Src/Editor/Hotfix.cs index 58ca2d0..918bacc 100644 --- a/Assets/XLua/Src/Editor/Hotfix.cs +++ b/Assets/XLua/Src/Editor/Hotfix.cs @@ -431,6 +431,29 @@ namespace XLua } } + List toAdd = new List(); + foreach (var method in type.Methods) + { + if (ignoreNotPublic && !method.IsPublic) + { + continue; + } + if (ignoreProperty && method.IsSpecialName && (method.Name.StartsWith("get_") || method.Name.StartsWith("set_"))) + { + continue; + } + if (method.Name != ".cctor" && !method.IsAbstract && !method.IsPInvokeImpl && method.Body != null && !method.Name.Contains("<")) + { + var proxyMethod = tryAddBaseProxy(method.DeclaringType, method); + if (proxyMethod != null) toAdd.Add(proxyMethod); + } + } + + foreach(var md in toAdd) + { + type.Methods.Add(md); + } + return true; } @@ -591,6 +614,87 @@ namespace XLua return null; } + static MethodDefinition findOverride(TypeDefinition type, MethodReference vmethod) + { + foreach (var method in type.Methods) + { + if (method.Name == vmethod.Name && method.IsVirtual && isSameType(method.ReturnType, vmethod.ReturnType) && method.Parameters.Count == vmethod.Parameters.Count) + { + bool isParamsMatch = true; + for (int i = 0; i < method.Parameters.Count; i++) + { + if (method.Parameters[i].Attributes != vmethod.Parameters[i].Attributes + || !isSameType(method.Parameters[i].ParameterType, vmethod.Parameters[i].ParameterType)) + { + isParamsMatch = false; + break; + } + } + if (isParamsMatch) return method; + } + } + return null; + } + + static MethodReference findBase(TypeDefinition type, MethodDefinition method) + { + if (method.IsVirtual && !method.IsNewSlot) //表明override + { + try + { + TypeDefinition tbase = type.BaseType.Resolve(); + while (tbase != null) + { + var m = findOverride(tbase, method); + if (m != null) + { + return m; + } + tbase = tbase.BaseType.Resolve(); + } + } + catch { } + } + return null; + } + + const string BASE_RPOXY_PERFIX = "<>xLuaBaseProxy_"; + + static MethodDefinition tryAddBaseProxy(TypeDefinition type, MethodDefinition method) + { + var mbase = findBase(type, method); + if (mbase != null) + { + var proxyMethod = new MethodDefinition(BASE_RPOXY_PERFIX + method.Name, Mono.Cecil.MethodAttributes.Public, method.ReturnType); + for (int i = 0; i < method.Parameters.Count; i++) + { + proxyMethod.Parameters.Add(new ParameterDefinition("P" + i, method.Parameters[i].IsOut ? Mono.Cecil.ParameterAttributes.Out : Mono.Cecil.ParameterAttributes.None, method.Parameters[i].ParameterType)); + } + var instructions = proxyMethod.Body.Instructions; + var processor = proxyMethod.Body.GetILProcessor(); + int paramCount = method.Parameters.Count + 1; + for (int i = 0; i < paramCount; i++) + { + if (i < ldargs.Length) + { + instructions.Add(processor.Create(ldargs[i])); + } + else if (i < 256) + { + instructions.Add(processor.Create(OpCodes.Ldarg_S, (byte)i)); + } + else + { + instructions.Add(processor.Create(OpCodes.Ldarg, (short)i)); + } + } + instructions.Add(Instruction.Create(OpCodes.Call, mbase)); + instructions.Add(Instruction.Create(OpCodes.Ret)); + return proxyMethod; + } + return null; + } + static bool injectMethod(AssemblyDefinition assembly, MethodDefinition method, HotfixFlagInTool hotfixType, FieldReference stateTable) { var type = method.DeclaringType; diff --git a/Assets/XLua/Src/LuaEnv.cs b/Assets/XLua/Src/LuaEnv.cs index 27c64aa..789bc32 100644 --- a/Assets/XLua/Src/LuaEnv.cs +++ b/Assets/XLua/Src/LuaEnv.cs @@ -554,6 +554,19 @@ namespace XLua impl.UnderlyingSystemType = parent[name].UnderlyingSystemType rawset(parent, name, impl) end + + local base_mt = { + __index = function(t, k) + local csobj = t['__csobj'] + local func = csobj['<>xLuaBaseProxy_'..k] + return function(_, ...) + func(csobj, ...) + end + end + } + base = function(csobj) + return setmetatable({__csobj = csobj}, base_mt) + end "; public delegate byte[] CustomLoader(ref string filepath); diff --git a/Tools/XLuaHotfixInject.exe b/Tools/XLuaHotfixInject.exe index d37fd85d436de0245a5ff1bd63c656cb0d965903..607b908023b9c77bff6a36dfd5704d1d70988cf0 100644 GIT binary patch delta 14594 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 delta 12886 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 a%VTTe_ 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 -- GitLab