@@ -156,56 +156,59 @@ public override int GetHashCode()
156
156
157
157
protected virtual MethodInfo GetMethodImpl ( )
158
158
{
159
- if ( _methodBase is null or not MethodInfo )
159
+ if ( _methodBase is MethodInfo methodInfo )
160
160
{
161
- IRuntimeMethodInfo method = FindMethodHandle ( ) ;
162
- RuntimeType ? declaringType = RuntimeMethodHandle . GetDeclaringType ( method ) ;
163
- // need a proper declaring type instance method on a generic type
164
- if ( declaringType . IsGenericType )
161
+ return methodInfo ;
162
+ }
163
+
164
+ IRuntimeMethodInfo method = FindMethodHandle ( ) ;
165
+ RuntimeType ? declaringType = RuntimeMethodHandle . GetDeclaringType ( method ) ;
166
+ // need a proper declaring type instance method on a generic type
167
+ if ( declaringType . IsGenericType )
168
+ {
169
+ bool isStatic = ( RuntimeMethodHandle . GetAttributes ( method ) & MethodAttributes . Static ) != ( MethodAttributes ) 0 ;
170
+ if ( ! isStatic )
165
171
{
166
- bool isStatic = ( RuntimeMethodHandle . GetAttributes ( method ) & MethodAttributes . Static ) != ( MethodAttributes ) 0 ;
167
- if ( ! isStatic )
172
+ if ( _methodPtrAux == IntPtr . Zero )
168
173
{
169
- if ( _methodPtrAux == IntPtr . Zero )
174
+ // The target may be of a derived type that doesn't have visibility onto the
175
+ // target method. We don't want to call RuntimeType.GetMethodBase below with that
176
+ // or reflection can end up generating a MethodInfo where the ReflectedType cannot
177
+ // see the MethodInfo itself and that breaks an important invariant. But the
178
+ // target type could include important generic type information we need in order
179
+ // to work out what the exact instantiation of the method's declaring type is. So
180
+ // we'll walk up the inheritance chain (which will yield exactly instantiated
181
+ // types at each step) until we find the declaring type. Since the declaring type
182
+ // we get from the method is probably shared and those in the hierarchy we're
183
+ // walking won't be we compare using the generic type definition forms instead.
184
+ Type ? currentType = _target ! . GetType ( ) ;
185
+ Type targetType = declaringType . GetGenericTypeDefinition ( ) ;
186
+ while ( currentType != null )
170
187
{
171
- // The target may be of a derived type that doesn't have visibility onto the
172
- // target method. We don't want to call RuntimeType.GetMethodBase below with that
173
- // or reflection can end up generating a MethodInfo where the ReflectedType cannot
174
- // see the MethodInfo itself and that breaks an important invariant. But the
175
- // target type could include important generic type information we need in order
176
- // to work out what the exact instantiation of the method's declaring type is. So
177
- // we'll walk up the inheritance chain (which will yield exactly instantiated
178
- // types at each step) until we find the declaring type. Since the declaring type
179
- // we get from the method is probably shared and those in the hierarchy we're
180
- // walking won't be we compare using the generic type definition forms instead.
181
- Type ? currentType = _target ! . GetType ( ) ;
182
- Type targetType = declaringType . GetGenericTypeDefinition ( ) ;
183
- while ( currentType != null )
188
+ if ( currentType . IsGenericType &&
189
+ currentType . GetGenericTypeDefinition ( ) == targetType )
184
190
{
185
- if ( currentType . IsGenericType &&
186
- currentType . GetGenericTypeDefinition ( ) == targetType )
187
- {
188
- declaringType = currentType as RuntimeType ;
189
- break ;
190
- }
191
- currentType = currentType . BaseType ;
191
+ declaringType = currentType as RuntimeType ;
192
+ break ;
192
193
}
193
-
194
- // RCWs don't need to be "strongly-typed" in which case we don't find a base type
195
- // that matches the declaring type of the method. This is fine because interop needs
196
- // to work with exact methods anyway so declaringType is never shared at this point.
197
- Debug . Assert ( currentType != null || _target . GetType ( ) . IsCOMObject , "The class hierarchy should declare the method" ) ;
198
- }
199
- else
200
- {
201
- // it's an open one, need to fetch the first arg of the instantiation
202
- MethodInfo invoke = this . GetType ( ) . GetMethod ( "Invoke" ) ! ;
203
- declaringType = ( RuntimeType ) invoke . GetParametersAsSpan ( ) [ 0 ] . ParameterType ;
194
+ currentType = currentType . BaseType ;
204
195
}
196
+
197
+ // RCWs don't need to be "strongly-typed" in which case we don't find a base type
198
+ // that matches the declaring type of the method. This is fine because interop needs
199
+ // to work with exact methods anyway so declaringType is never shared at this point.
200
+ Debug . Assert ( currentType != null || _target . GetType ( ) . IsCOMObject , "The class hierarchy should declare the method" ) ;
201
+ }
202
+ else
203
+ {
204
+ // it's an open one, need to fetch the first arg of the instantiation
205
+ MethodInfo invoke = this . GetType ( ) . GetMethod ( "Invoke" ) ! ;
206
+ declaringType = ( RuntimeType ) invoke . GetParametersAsSpan ( ) [ 0 ] . ParameterType ;
205
207
}
206
208
}
207
- _methodBase = ( MethodInfo ) RuntimeType . GetMethodBase ( declaringType , method ) ! ;
208
209
}
210
+
211
+ _methodBase = ( MethodInfo ) RuntimeType . GetMethodBase ( declaringType , method ) ! ;
209
212
return ( MethodInfo ) _methodBase ;
210
213
}
211
214
0 commit comments