@@ -426,13 +426,78 @@ internal void AddInterfaceImpl(Type iface)
426426 _assembly . EnsureTypeIsVisible ( iface ) ;
427427
428428 _tb . AddInterfaceImplementation ( iface ) ;
429+
430+ // AccessorMethods -> Metadata mappings.
431+ var propertyMap = new Dictionary < MethodInfo , PropertyAccessorInfo > ( MethodInfoEqualityComparer . Instance ) ;
432+ foreach ( PropertyInfo pi in iface . GetRuntimeProperties ( ) )
433+ {
434+ var ai = new PropertyAccessorInfo ( pi . GetMethod , pi . SetMethod ) ;
435+ if ( pi . GetMethod != null )
436+ propertyMap [ pi . GetMethod ] = ai ;
437+ if ( pi . SetMethod != null )
438+ propertyMap [ pi . SetMethod ] = ai ;
439+ }
440+
441+ var eventMap = new Dictionary < MethodInfo , EventAccessorInfo > ( MethodInfoEqualityComparer . Instance ) ;
442+ foreach ( EventInfo ei in iface . GetRuntimeEvents ( ) )
443+ {
444+ var ai = new EventAccessorInfo ( ei . AddMethod , ei . RemoveMethod , ei . RaiseMethod ) ;
445+ if ( ei . AddMethod != null )
446+ eventMap [ ei . AddMethod ] = ai ;
447+ if ( ei . RemoveMethod != null )
448+ eventMap [ ei . RemoveMethod ] = ai ;
449+ if ( ei . RaiseMethod != null )
450+ eventMap [ ei . RaiseMethod ] = ai ;
451+ }
452+
429453 foreach ( MethodInfo mi in iface . GetRuntimeMethods ( ) )
430454 {
431- AddMethodImpl ( mi ) ;
455+ MethodBuilder mdb = AddMethodImpl ( mi ) ;
456+ PropertyAccessorInfo associatedProperty ;
457+ if ( propertyMap . TryGetValue ( mi , out associatedProperty ) )
458+ {
459+ if ( MethodInfoEqualityComparer . Instance . Equals ( associatedProperty . InterfaceGetMethod , mi ) )
460+ associatedProperty . GetMethodBuilder = mdb ;
461+ else
462+ associatedProperty . SetMethodBuilder = mdb ;
463+ }
464+
465+ EventAccessorInfo associatedEvent ;
466+ if ( eventMap . TryGetValue ( mi , out associatedEvent ) )
467+ {
468+ if ( MethodInfoEqualityComparer . Instance . Equals ( associatedEvent . InterfaceAddMethod , mi ) )
469+ associatedEvent . AddMethodBuilder = mdb ;
470+ else if ( MethodInfoEqualityComparer . Instance . Equals ( associatedEvent . InterfaceRemoveMethod , mi ) )
471+ associatedEvent . RemoveMethodBuilder = mdb ;
472+ else
473+ associatedEvent . RaiseMethodBuilder = mdb ;
474+ }
475+ }
476+
477+ foreach ( PropertyInfo pi in iface . GetRuntimeProperties ( ) )
478+ {
479+ PropertyAccessorInfo ai = propertyMap [ pi . GetMethod ?? pi . SetMethod ] ;
480+ PropertyBuilder pb = _tb . DefineProperty ( pi . Name , pi . Attributes , pi . PropertyType , pi . GetIndexParameters ( ) . Select ( p => p . ParameterType ) . ToArray ( ) ) ;
481+ if ( ai . GetMethodBuilder != null )
482+ pb . SetGetMethod ( ai . GetMethodBuilder ) ;
483+ if ( ai . SetMethodBuilder != null )
484+ pb . SetSetMethod ( ai . SetMethodBuilder ) ;
485+ }
486+
487+ foreach ( EventInfo ei in iface . GetRuntimeEvents ( ) )
488+ {
489+ EventAccessorInfo ai = eventMap [ ei . AddMethod ?? ei . RemoveMethod ] ;
490+ EventBuilder eb = _tb . DefineEvent ( ei . Name , ei . Attributes , ei . EventHandlerType ) ;
491+ if ( ai . AddMethodBuilder != null )
492+ eb . SetAddOnMethod ( ai . AddMethodBuilder ) ;
493+ if ( ai . RemoveMethodBuilder != null )
494+ eb . SetRemoveOnMethod ( ai . RemoveMethodBuilder ) ;
495+ if ( ai . RaiseMethodBuilder != null )
496+ eb . SetRaiseMethod ( ai . RaiseMethodBuilder ) ;
432497 }
433498 }
434499
435- private void AddMethodImpl ( MethodInfo mi )
500+ private MethodBuilder AddMethodImpl ( MethodInfo mi )
436501 {
437502 ParameterInfo [ ] parameters = mi . GetParameters ( ) ;
438503 Type [ ] paramTypes = ParamTypes ( parameters , false ) ;
@@ -541,6 +606,7 @@ private void AddMethodImpl(MethodInfo mi)
541606 il . Emit ( OpCodes . Ret ) ;
542607
543608 _tb . DefineMethodOverride ( mdb , mi ) ;
609+ return mdb ;
544610 }
545611
546612 private static Type [ ] ParamTypes ( ParameterInfo [ ] parms , bool noByRef )
@@ -831,6 +897,112 @@ internal void EndSet(Type stackType)
831897 _il . Emit ( OpCodes . Stelem_Ref ) ;
832898 }
833899 }
900+
901+ private sealed class PropertyAccessorInfo
902+ {
903+ public MethodInfo InterfaceGetMethod { get ; }
904+ public MethodInfo InterfaceSetMethod { get ; }
905+ public MethodBuilder GetMethodBuilder { get ; set ; }
906+ public MethodBuilder SetMethodBuilder { get ; set ; }
907+
908+ public PropertyAccessorInfo ( MethodInfo interfaceGetMethod , MethodInfo interfaceSetMethod )
909+ {
910+ InterfaceGetMethod = interfaceGetMethod ;
911+ InterfaceSetMethod = interfaceSetMethod ;
912+ }
913+ }
914+
915+ private sealed class EventAccessorInfo
916+ {
917+ public MethodInfo InterfaceAddMethod { get ; }
918+ public MethodInfo InterfaceRemoveMethod { get ; }
919+ public MethodInfo InterfaceRaiseMethod { get ; }
920+ public MethodBuilder AddMethodBuilder { get ; set ; }
921+ public MethodBuilder RemoveMethodBuilder { get ; set ; }
922+ public MethodBuilder RaiseMethodBuilder { get ; set ; }
923+
924+ public EventAccessorInfo ( MethodInfo interfaceAddMethod , MethodInfo interfaceRemoveMethod , MethodInfo interfaceRaiseMethod )
925+ {
926+ InterfaceAddMethod = interfaceAddMethod ;
927+ InterfaceRemoveMethod = interfaceRemoveMethod ;
928+ InterfaceRaiseMethod = interfaceRaiseMethod ;
929+ }
930+ }
931+
932+ private sealed class MethodInfoEqualityComparer : EqualityComparer < MethodInfo >
933+ {
934+ public static readonly MethodInfoEqualityComparer Instance = new MethodInfoEqualityComparer ( ) ;
935+
936+ private MethodInfoEqualityComparer ( ) { }
937+
938+ public sealed override bool Equals ( MethodInfo left , MethodInfo right )
939+ {
940+ if ( ReferenceEquals ( left , right ) )
941+ return true ;
942+
943+ if ( left == null )
944+ return right == null ;
945+ else if ( right == null )
946+ return false ;
947+
948+ // This assembly should work in netstandard1.3,
949+ // so we cannot use MemberInfo.MetadataToken here.
950+ // Therefore, it compares honestly referring ECMA-335 I.8.6.1.6 Signature Matching.
951+ if ( ! Equals ( left . DeclaringType , right . DeclaringType ) )
952+ return false ;
953+
954+ if ( ! Equals ( left . ReturnType , right . ReturnType ) )
955+ return false ;
956+
957+ if ( left . CallingConvention != right . CallingConvention )
958+ return false ;
959+
960+ if ( left . IsStatic != right . IsStatic )
961+ return false ;
962+
963+ if ( left . Name != right . Name )
964+ return false ;
965+
966+ Type [ ] leftGenericParameters = left . GetGenericArguments ( ) ;
967+ Type [ ] rightGenericParameters = right . GetGenericArguments ( ) ;
968+ if ( leftGenericParameters . Length != rightGenericParameters . Length )
969+ return false ;
970+
971+ for ( int i = 0 ; i < leftGenericParameters . Length ; i ++ )
972+ {
973+ if ( ! Equals ( leftGenericParameters [ i ] , rightGenericParameters [ i ] ) )
974+ return false ;
975+ }
976+
977+ ParameterInfo [ ] leftParameters = left . GetParameters ( ) ;
978+ ParameterInfo [ ] rightParameters = right . GetParameters ( ) ;
979+ if ( leftParameters . Length != rightParameters . Length )
980+ return false ;
981+
982+ for ( int i = 0 ; i < leftParameters . Length ; i ++ )
983+ {
984+ if ( ! Equals ( leftParameters [ i ] . ParameterType , rightParameters [ i ] . ParameterType ) )
985+ return false ;
986+ }
987+
988+ return true ;
989+ }
990+
991+ public sealed override int GetHashCode ( MethodInfo obj )
992+ {
993+ if ( obj == null )
994+ return 0 ;
995+
996+ int hashCode = obj . DeclaringType . GetHashCode ( ) ;
997+ hashCode ^= obj . Name . GetHashCode ( ) ;
998+ foreach ( ParameterInfo parameter in obj . GetParameters ( ) )
999+ {
1000+ hashCode ^= parameter . ParameterType . GetHashCode ( ) ;
1001+ }
1002+
1003+ return hashCode ;
1004+ }
1005+ }
8341006 }
8351007 }
8361008}
0 commit comments