@@ -292,6 +292,8 @@ public static bool MemberIsHidden(MetadataFile module, EntityHandle member, Deco
292292 name = metadata . GetString ( method . Name ) ;
293293 if ( name == ".ctor" && method . RelativeVirtualAddress == 0 && metadata . GetTypeDefinition ( method . GetDeclaringType ( ) ) . Attributes . HasFlag ( System . Reflection . TypeAttributes . Import ) )
294294 return true ;
295+ if ( module is PEFile m && IsAccessorInterfaceImplementationRuntimeHelper ( m , methodHandle ) )
296+ return true ;
295297 if ( settings . LocalFunctions && LocalFunctionDecompiler . IsLocalFunctionMethod ( module , methodHandle ) )
296298 return true ;
297299 if ( settings . AnonymousMethods && methodHandle . HasGeneratedName ( metadata ) && methodHandle . IsCompilerGenerated ( metadata ) )
@@ -386,6 +388,163 @@ static bool IsPrimaryConstructorParameterBackingField(SRM.FieldDefinition field,
386388 return name . StartsWith ( "<" , StringComparison . Ordinal ) && name . EndsWith ( ">P" , StringComparison . Ordinal ) ;
387389 }
388390
391+ static bool IsAccessorInterfaceImplementationRuntimeHelper ( PEFile module , MethodDefinitionHandle handle )
392+ {
393+ var metadata = module . Metadata ;
394+ var method = metadata . GetMethodDefinition ( handle ) ;
395+ if ( ( method . Attributes & System . Reflection . MethodAttributes . Static ) != 0 )
396+ return false ;
397+ string rawName = metadata . GetString ( method . Name ) ;
398+ int dot = rawName . LastIndexOf ( '.' ) ;
399+ if ( dot < 0 )
400+ return false ;
401+ string name = rawName . Substring ( dot + 1 ) ;
402+ if ( handle . GetMethodImplementations ( metadata ) . Length == 0 )
403+ return false ;
404+ if ( method . RelativeVirtualAddress == 0 )
405+ return false ;
406+ if ( ! name . StartsWith ( "get_" , StringComparison . Ordinal ) &&
407+ ! name . StartsWith ( "set_" , StringComparison . Ordinal ) &&
408+ ! name . StartsWith ( "add_" , StringComparison . Ordinal ) &&
409+ ! name . StartsWith ( "remove_" , StringComparison . Ordinal ) &&
410+ ! name . StartsWith ( "raise_" , StringComparison . Ordinal ) )
411+ {
412+ return false ;
413+ }
414+
415+ var signature = metadata . GetBlobReader ( method . Signature ) ;
416+ ( int genericParameterCount , int parameterCount ) = SignatureBlobComparer . ReadParameterCount ( ref signature ) ;
417+ if ( genericParameterCount == - 1 || parameterCount == - 1 )
418+ return false ;
419+ signature . Reset ( ) ;
420+
421+ int maximumMethodSize = 4 * ( parameterCount + 1 ) + 5 + 1 ;
422+
423+ var body = module . Reader . GetMethodBody ( method . RelativeVirtualAddress ) ;
424+ var reader = body . GetILReader ( ) ;
425+
426+ if ( reader . RemainingBytes > maximumMethodSize )
427+ return false ;
428+
429+ for ( int i = 0 ; i < parameterCount + 1 ; i ++ )
430+ {
431+ int index ;
432+ switch ( reader . DecodeOpCode ( ) )
433+ {
434+ case ILOpCode . Ldarg :
435+ index = reader . ReadUInt16 ( ) ;
436+ if ( index != i )
437+ return false ;
438+ break ;
439+ case ILOpCode . Ldarg_s :
440+ index = reader . ReadByte ( ) ;
441+ if ( index != i )
442+ return false ;
443+ break ;
444+ case ILOpCode . Ldarg_0 :
445+ if ( i != 0 )
446+ return false ;
447+ break ;
448+ case ILOpCode . Ldarg_1 :
449+ if ( i != 1 )
450+ return false ;
451+ break ;
452+ case ILOpCode . Ldarg_2 :
453+ if ( i != 2 )
454+ return false ;
455+ break ;
456+ case ILOpCode . Ldarg_3 :
457+ if ( i != 3 )
458+ return false ;
459+ break ;
460+ default :
461+ return false ;
462+ }
463+ }
464+
465+ if ( reader . DecodeOpCode ( ) != ILOpCode . Call )
466+ return false ;
467+
468+ EntityHandle targetHandle = MetadataTokenHelpers . EntityHandleOrNil ( reader . ReadInt32 ( ) ) ;
469+ if ( targetHandle . IsNil )
470+ return false ;
471+
472+ if ( reader . DecodeOpCode ( ) != ILOpCode . Ret )
473+ return false ;
474+
475+ if ( reader . RemainingBytes != 0 )
476+ return false ;
477+
478+ BlobReader signature2 ;
479+ string otherName ;
480+
481+ switch ( targetHandle . Kind )
482+ {
483+ case HandleKind . MethodDefinition :
484+ if ( genericParameterCount != 0 )
485+ return false ;
486+ var methodDef = metadata . GetMethodDefinition ( ( MethodDefinitionHandle ) targetHandle ) ;
487+ signature2 = metadata . GetBlobReader ( methodDef . Signature ) ;
488+ otherName = metadata . GetString ( methodDef . Name ) ;
489+ break ;
490+ case HandleKind . MethodSpecification :
491+ if ( genericParameterCount == 0 )
492+ return false ;
493+ var methodSpec = metadata . GetMethodSpecification ( ( MethodSpecificationHandle ) targetHandle ) ;
494+ var instantiationBlob = metadata . GetBlobReader ( methodSpec . Signature ) ;
495+ if ( ! IsIdentityInstantiation ( ref instantiationBlob , genericParameterCount ) )
496+ return false ;
497+ switch ( methodSpec . Method . Kind )
498+ {
499+ case HandleKind . MethodDefinition :
500+ var methodSpecDef = metadata . GetMethodDefinition ( ( MethodDefinitionHandle ) methodSpec . Method ) ;
501+ signature2 = metadata . GetBlobReader ( methodSpecDef . Signature ) ;
502+ otherName = metadata . GetString ( methodSpecDef . Name ) ;
503+ break ;
504+ case HandleKind . MemberReference :
505+ var methodSpecRef = metadata . GetMemberReference ( ( MemberReferenceHandle ) methodSpec . Method ) ;
506+ if ( methodSpecRef . GetKind ( ) != MemberReferenceKind . Method )
507+ return false ;
508+ signature2 = metadata . GetBlobReader ( methodSpecRef . Signature ) ;
509+ otherName = metadata . GetString ( methodSpecRef . Name ) ;
510+ break ;
511+ default :
512+ return false ;
513+ }
514+ break ;
515+ case HandleKind . MemberReference :
516+ var methodRef = metadata . GetMemberReference ( ( MemberReferenceHandle ) targetHandle ) ;
517+ if ( methodRef . GetKind ( ) != MemberReferenceKind . Method )
518+ return false ;
519+ signature2 = metadata . GetBlobReader ( methodRef . Signature ) ;
520+ otherName = metadata . GetString ( methodRef . Name ) ;
521+ break ;
522+ default :
523+ return false ;
524+ }
525+
526+ if ( otherName != name )
527+ return false ;
528+ return SignatureBlobComparer . EqualsMethodSignature ( signature , signature2 , metadata , metadata , skipModifiers : true ) ;
529+
530+ static bool IsIdentityInstantiation ( ref BlobReader reader , int expectedCount )
531+ {
532+ // Format: GENRICINST count type1 type2 ...
533+ if ( reader . ReadByte ( ) != 0x0A ) // GENERICINST
534+ return false ;
535+ if ( ! reader . TryReadCompressedInteger ( out int count ) || count != expectedCount )
536+ return false ;
537+ for ( int i = 0 ; i < count ; i ++ )
538+ {
539+ if ( reader . ReadByte ( ) != 0x1E ) // ELEMENT_TYPE_MVAR
540+ return false ;
541+ if ( ! reader . TryReadCompressedInteger ( out int index ) || index != i )
542+ return false ;
543+ }
544+ return true ;
545+ }
546+ }
547+
389548 static bool IsSwitchOnStringCache ( SRM . FieldDefinition field , MetadataReader metadata )
390549 {
391550 return metadata . GetString ( field . Name ) . StartsWith ( "<>f__switch" , StringComparison . Ordinal ) ;
0 commit comments