提交 b9aad836 编写于 作者: J johnche(车雄生)

支持在子类override函数通过base调用父类实现。

上级 a26aa61c
......@@ -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的执行会略慢。
......
......@@ -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()
......
......@@ -431,6 +431,29 @@ namespace XLua
}
}
List<MethodDefinition> toAdd = new List<MethodDefinition>();
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;
......
......@@ -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);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册