@@ -53,8 +53,10 @@ public DefaultMethodEmitter(IArgumentHandler argumentHandler)
5353
5454 #region IMethodBodyEmitter Members
5555
56- public void EmitMethodBody ( ILGenerator IL , MethodInfo method , FieldInfo field )
56+ public void EmitMethodBody ( MethodBuilder generatedMethod , MethodInfo method , FieldInfo field )
5757 {
58+ var IL = generatedMethod . GetILGenerator ( ) ;
59+
5860 ParameterInfo [ ] parameters = method . GetParameters ( ) ;
5961 IL . DeclareLocal ( typeof ( object [ ] ) ) ;
6062 IL . DeclareLocal ( typeof ( InvocationInfo ) ) ;
@@ -73,33 +75,17 @@ public void EmitMethodBody(ILGenerator IL, MethodInfo method, FieldInfo field)
7375
7476 IL . Emit ( OpCodes . Ldarg_0 ) ;
7577
76- for ( int i = 0 ; i < method . GetParameters ( ) . Length ; i ++ )
78+ for ( int i = 0 ; i < method . GetParameters ( ) . Length ; i ++ )
7779 IL . Emit ( OpCodes . Ldarg_S , ( sbyte ) ( i + 1 ) ) ;
7880
7981 IL . Emit ( OpCodes . Call , method ) ;
8082 IL . Emit ( OpCodes . Ret ) ;
8183
8284 IL . MarkLabel ( skipBaseCall ) ;
8385
84- // Push the 'this' pointer onto the stack
85- IL . Emit ( OpCodes . Ldarg_0 ) ;
86-
87- // Push the MethodInfo onto the stack
88- System . Type declaringType = method . DeclaringType ;
89-
90- IL . Emit ( OpCodes . Ldtoken , method ) ;
91- if ( declaringType . IsGenericType )
92- {
93- IL . Emit ( OpCodes . Ldtoken , declaringType ) ;
94- IL . Emit ( OpCodes . Call , getGenericMethodFromHandle ) ;
95- }
96- else
97- {
98- IL . Emit ( OpCodes . Call , getMethodFromHandle ) ;
99- }
100-
101- IL . Emit ( OpCodes . Castclass , typeof ( MethodInfo ) ) ;
102-
86+ // Push arguments for InvocationInfo constructor.
87+ IL . Emit ( OpCodes . Ldarg_0 ) ; // 'this' pointer
88+ PushTargetMethodInfo ( IL , generatedMethod , method ) ;
10389 PushStackTrace ( IL ) ;
10490 PushGenericArguments ( method , IL ) ;
10591 _argumentHandler . PushArguments ( parameters , IL , false ) ;
@@ -172,6 +158,44 @@ private static OpCode GetStindInstruction(System.Type parameterType)
172158 return OpCodes . Stind_Ref ;
173159 }
174160
161+ private static void PushTargetMethodInfo ( ILGenerator IL , MethodBuilder generatedMethod , MethodInfo method )
162+ {
163+ if ( method . IsGenericMethodDefinition )
164+ {
165+ // We want the generated code to load a MethodInfo instantiated with the
166+ // current generic type parameters. I.e.:
167+ // MethodInfo methodInfo = methodof(TheClass.TheMethod<T>(...)
168+ //
169+ // We need to instantiate the open generic method definition with the type
170+ // arguments from the generated method. Using the open method definition
171+ // directly works on .Net 2.0, which might be FW bug, but fails on 4.0.
172+ //
173+ // Equivalent pseudo-code:
174+ // MethodInfo mi = methodof(TheClass.TheMethod<>)
175+ // versus
176+ // MethodInfo mi = methodof(TheClass.TheMethod<T0>)
177+ var instantiatedMethod = method . MakeGenericMethod ( generatedMethod . GetGenericArguments ( ) ) ;
178+ IL . Emit ( OpCodes . Ldtoken , instantiatedMethod ) ;
179+ }
180+ else
181+ {
182+ IL . Emit ( OpCodes . Ldtoken , method ) ;
183+ }
184+
185+ System . Type declaringType = method . DeclaringType ;
186+ if ( declaringType . IsGenericType )
187+ {
188+ IL . Emit ( OpCodes . Ldtoken , declaringType ) ;
189+ IL . Emit ( OpCodes . Call , getGenericMethodFromHandle ) ;
190+ }
191+ else
192+ {
193+ IL . Emit ( OpCodes . Call , getMethodFromHandle ) ;
194+ }
195+
196+ IL . Emit ( OpCodes . Castclass , typeof ( MethodInfo ) ) ;
197+ }
198+
175199 private void PushStackTrace ( ILGenerator IL )
176200 {
177201 // NOTE: The stack trace has been disabled for performance reasons
0 commit comments