Skip to content

Commit 1486747

Browse files
committed
assembly-csharp之外的dll注入,改为使用delegate方式
1 parent e889fc2 commit 1486747

3 files changed

Lines changed: 101 additions & 8 deletions

File tree

Assets/XLua/Src/Editor/Hotfix.cs

Lines changed: 101 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,11 +254,17 @@ public class Hotfix
254254

255255
private Dictionary<string, int> hotfixCfg = null;
256256
private List<MethodDefinition> hotfixBridgesDef = null;
257+
private Dictionary<MethodDefinition, MethodDefinition> hotfixBridgeToDelegate = null;
257258

258259
private List<MethodDefinition> bridgeIndexByKey = null;
259260

261+
private bool isTheSameAssembly = false;
262+
263+
private int delegateId = 0;
264+
260265
public void Init(AssemblyDefinition injectAssembly, AssemblyDefinition xluaAssembly, IEnumerable<string> searchDirectorys, Dictionary<string, int> hotfixCfg)
261266
{
267+
isTheSameAssembly = injectAssembly == xluaAssembly;
262268
this.injectAssembly = injectAssembly;
263269
this.hotfixCfg = hotfixCfg;
264270
var injectModule = injectAssembly.MainModule;
@@ -283,21 +289,23 @@ public void Init(AssemblyDefinition injectAssembly, AssemblyDefinition xluaAssem
283289
hotfixBridgesDef = (from method in delegateBridgeTypeDef.Methods
284290
where method.Name.StartsWith("__Gen_Delegate_Imp")
285291
select method).ToList();
292+
hotfixBridgeToDelegate = new Dictionary<MethodDefinition, MethodDefinition>();
293+
delegateId = 0;
286294

287295
//hotfixBridges = hotfixBridgesDef.Select(m => injectModule.TryImport(m)).ToList();
288296

289297
bridgeIndexByKey = new List<MethodDefinition>();
290298

291299
var resolverOfInjectAssembly = injectAssembly.MainModule.AssemblyResolver as BaseAssemblyResolver;
292300
var resolverOfXluaAssembly = xluaAssembly.MainModule.AssemblyResolver as BaseAssemblyResolver;
293-
if (injectAssembly != xluaAssembly)
301+
if (!isTheSameAssembly)
294302
{
295303
resolverOfXluaAssembly.AddSearchDirectory(Path.GetDirectoryName(injectAssembly.MainModule.FullyQualifiedName));
296304
}
297305
Action<string> addSearchDirectory = (string dir) =>
298306
{
299307
resolverOfInjectAssembly.AddSearchDirectory(dir);
300-
if (injectAssembly != xluaAssembly)
308+
if (!isTheSameAssembly)
301309
{
302310
resolverOfXluaAssembly.AddSearchDirectory(dir);
303311
}
@@ -382,6 +390,91 @@ static bool isSameType(TypeReference left, TypeReference right)
382390
}
383391
}
384392

393+
MethodDefinition createDelegateFor(MethodDefinition method, AssemblyDefinition assembly, string delegateName, bool ignoreValueType)
394+
{
395+
var voidType = assembly.MainModule.TypeSystem.Void;
396+
var objectType = assembly.MainModule.TypeSystem.Object;
397+
var nativeIntType = assembly.MainModule.TypeSystem.IntPtr;
398+
var asyncResultType = assembly.MainModule.Import(typeof(IAsyncResult));
399+
var asyncCallbackType = assembly.MainModule.Import(typeof(AsyncCallback));
400+
401+
Mono.Cecil.MethodAttributes delegateMethodAttributes = Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.HideBySig | Mono.Cecil.MethodAttributes.Virtual | Mono.Cecil.MethodAttributes.VtableLayoutMask;
402+
403+
var delegateDef = new TypeDefinition("XLua", delegateName, Mono.Cecil.TypeAttributes.Sealed | Mono.Cecil.TypeAttributes.Public,
404+
assembly.MainModule.Import(typeof(MulticastDelegate)));
405+
List<TypeReference> argTypes = new List<TypeReference>();
406+
TypeReference self = null;
407+
if (!method.IsStatic)
408+
{
409+
self = (!ignoreValueType && method.DeclaringType.IsValueType) ? method.DeclaringType : objType;
410+
}
411+
foreach(var parameter in method.Parameters)
412+
{
413+
bool isparam = parameter.CustomAttributes.FirstOrDefault(ca => ca.AttributeType.Name == "ParamArrayAttribute") != null;
414+
argTypes.Add((isparam || parameter.ParameterType.IsByReference || (!ignoreValueType && parameter.ParameterType.IsValueType)) ? parameter.ParameterType : objType);
415+
}
416+
417+
var constructor = new MethodDefinition(".ctor", Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.HideBySig | Mono.Cecil.MethodAttributes.SpecialName | Mono.Cecil.MethodAttributes.RTSpecialName, voidType);
418+
constructor.Parameters.Add(new ParameterDefinition("objectInstance", Mono.Cecil.ParameterAttributes.None, objectType));
419+
constructor.Parameters.Add(new ParameterDefinition("functionPtr", Mono.Cecil.ParameterAttributes.None, nativeIntType));
420+
constructor.ImplAttributes = Mono.Cecil.MethodImplAttributes.Runtime;
421+
delegateDef.Methods.Add(constructor);
422+
423+
var beginInvoke = new MethodDefinition("BeginInvoke", delegateMethodAttributes, asyncResultType);
424+
if (self != null)
425+
{
426+
beginInvoke.Parameters.Add(new ParameterDefinition(self));
427+
}
428+
for (int i = 0; i < argTypes.Count; i++)
429+
{
430+
beginInvoke.Parameters.Add(new ParameterDefinition(method.Parameters[i].Name, (method.Parameters[i].IsOut ? Mono.Cecil.ParameterAttributes.Out : Mono.Cecil.ParameterAttributes.None), argTypes[i]));
431+
}
432+
beginInvoke.Parameters.Add(new ParameterDefinition("callback", Mono.Cecil.ParameterAttributes.None, asyncCallbackType));
433+
beginInvoke.Parameters.Add(new ParameterDefinition("object", Mono.Cecil.ParameterAttributes.None, objectType));
434+
beginInvoke.ImplAttributes = Mono.Cecil.MethodImplAttributes.Runtime;
435+
delegateDef.Methods.Add(beginInvoke);
436+
437+
var endInvoke = new MethodDefinition("EndInvoke", delegateMethodAttributes, method.ReturnType);
438+
for (int i = 0; i < argTypes.Count; i++)
439+
{
440+
if (argTypes[i].IsByReference)
441+
{
442+
endInvoke.Parameters.Add(new ParameterDefinition(method.Parameters[i].Name, (method.Parameters[i].IsOut ? Mono.Cecil.ParameterAttributes.Out : Mono.Cecil.ParameterAttributes.None), argTypes[i]));
443+
}
444+
}
445+
endInvoke.Parameters.Add(new ParameterDefinition("result", Mono.Cecil.ParameterAttributes.None, asyncResultType));
446+
endInvoke.ImplAttributes = Mono.Cecil.MethodImplAttributes.Runtime;
447+
delegateDef.Methods.Add(endInvoke);
448+
449+
var invoke = new MethodDefinition("Invoke", delegateMethodAttributes, method.ReturnType);
450+
if (self != null)
451+
{
452+
invoke.Parameters.Add(new ParameterDefinition(self));
453+
}
454+
foreach (var argType in argTypes)
455+
{
456+
invoke.Parameters.Add(new ParameterDefinition(argType));
457+
}
458+
invoke.ImplAttributes = Mono.Cecil.MethodImplAttributes.Runtime;
459+
delegateDef.Methods.Add(invoke);
460+
461+
assembly.MainModule.Types.Add(delegateDef);
462+
463+
return invoke;
464+
}
465+
466+
MethodDefinition getDelegateInvokeFor(MethodDefinition method, MethodDefinition bridgeDef, bool ignoreValueType)
467+
{
468+
MethodDefinition ret;
469+
if (!hotfixBridgeToDelegate.TryGetValue(bridgeDef, out ret))
470+
{
471+
ret = createDelegateFor(method, injectAssembly, ("__XLua_Gen_Delegate" + (delegateId++)), ignoreValueType);
472+
hotfixBridgeToDelegate.Add(bridgeDef, ret);
473+
}
474+
475+
return ret;
476+
}
477+
385478
bool findHotfixDelegate(MethodDefinition method, out MethodReference invoke, HotfixFlagInTool hotfixType)
386479
{
387480
bool ignoreValueType = hotfixType.HasFlag(HotfixFlagInTool.ValueTypeBoxing);
@@ -436,7 +529,7 @@ bool findHotfixDelegate(MethodDefinition method, out MethodReference invoke, Hot
436529
{
437530
continue;
438531
}
439-
invoke = hotfixBridgeDef;
532+
invoke = isTheSameAssembly ? hotfixBridgeDef : getDelegateInvokeFor(method, hotfixBridgeDef, ignoreValueType);
440533
return true;
441534
}
442535
}
@@ -736,14 +829,14 @@ public static void HotfixInject(string injectAssemblyPath, string xluaAssemblyPa
736829

737830
//var hotfixDelegateAttributeType = assembly.MainModule.Types.Single(t => t.FullName == "XLua.HotfixDelegateAttribute");
738831
var hotfixAttributeType = xluaAssembly.MainModule.Types.Single(t => t.FullName == "XLua.HotfixAttribute");
739-
foreach (var type in (from module in injectAssembly.Modules from type in module.Types select type))
832+
var toInject = (from module in injectAssembly.Modules from type in module.Types select type).ToList();
833+
foreach (var type in toInject)
740834
{
741835
if (!hotfix.InjectType(hotfixAttributeType, type))
742836
{
743837
return;
744838
}
745839
}
746-
747840
Directory.CreateDirectory(Path.GetDirectoryName(idMapFilePath));
748841
hotfix.OutputIntKeyMapper(new FileStream(idMapFilePath, FileMode.Create, FileAccess.Write));
749842
File.Copy(idMapFilePath, idMapFilePath + "." + DateTime.Now.ToString("yyyyMMddHHmmssfff"));
@@ -1052,12 +1145,12 @@ bool injectMethod(MethodDefinition method, HotfixFlagInTool hotfixType)
10521145

10531146
FieldReference fieldReference = null;
10541147
VariableDefinition injection = null;
1055-
bool isIntKey = hotfixType.HasFlag(HotfixFlagInTool.IntKey) && !type.HasGenericParameters;
1148+
bool isIntKey = hotfixType.HasFlag(HotfixFlagInTool.IntKey) && !type.HasGenericParameters && isTheSameAssembly;
10561149
//isIntKey = !type.HasGenericParameters;
10571150

10581151
if (!isIntKey)
10591152
{
1060-
injection = new VariableDefinition(delegateBridgeType);
1153+
injection = new VariableDefinition(invoke.DeclaringType);
10611154
method.Body.Variables.Add(injection);
10621155

10631156
var luaDelegateName = getDelegateName(method);
@@ -1068,7 +1161,7 @@ bool injectMethod(MethodDefinition method, HotfixFlagInTool hotfixType)
10681161
}
10691162

10701163
FieldDefinition fieldDefinition = new FieldDefinition(luaDelegateName, Mono.Cecil.FieldAttributes.Static | Mono.Cecil.FieldAttributes.Private,
1071-
delegateBridgeType);
1164+
invoke.DeclaringType);
10721165
type.Fields.Add(fieldDefinition);
10731166
fieldReference = fieldDefinition.GetGeneric();
10741167
}

Tools/XLuaHotfixInject.exe

2 KB
Binary file not shown.

Tools/XLuaHotfixInject.pdb

4 KB
Binary file not shown.

0 commit comments

Comments
 (0)