@@ -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 }
0 commit comments