@@ -392,10 +392,10 @@ internal static MethodBuilder DefineInterfaceImplMethod(MethodInfo method, TypeB
392392
393393 internal static void DefineInterfaceProxyMethods ( Type interfaceType , Type targetType , Type [ ] additionalInterfaces , TypeDesc typeDesc )
394394 {
395- var covariantReturnMethodMap = targetType . GetCovariantReturnMethods ( ) ;
395+ var covariantReturnMethods = targetType . GetCovariantReturnMethods ( ) ;
396396 foreach ( var method in interfaceType . GetTypeInfo ( ) . DeclaredMethods . Where ( x => ! x . IsPropertyBinding ( ) ) )
397397 {
398- var covariantReturnMethod = covariantReturnMethodMap
398+ var covariantReturnMethod = covariantReturnMethods
399399 . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( method ) )
400400 . CovariantReturnMethod ;
401401
@@ -405,7 +405,7 @@ internal static void DefineInterfaceProxyMethods(Type interfaceType, Type target
405405 {
406406 foreach ( var method in item . GetTypeInfo ( ) . DeclaredMethods . Where ( x => ! x . IsPropertyBinding ( ) ) )
407407 {
408- var covariantReturnMethod = covariantReturnMethodMap
408+ var covariantReturnMethod = covariantReturnMethods
409409 . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( method ) )
410410 . CovariantReturnMethod ;
411411
@@ -416,14 +416,28 @@ internal static void DefineInterfaceProxyMethods(Type interfaceType, Type target
416416
417417 internal static void DefineClassProxyMethods ( Type serviceType , Type implType , Type [ ] additionalInterfaces , TypeDesc typeDesc )
418418 {
419- var covariantReturnMethodMap = implType . GetCovariantReturnMethods ( ) ;
419+ var covariantReturnMethods = implType . GetCovariantReturnMethods ( ) ;
420420 foreach ( var method in serviceType . GetTypeInfo ( ) . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ) . Where ( x => ! x . IsPropertyBinding ( ) ) )
421421 {
422- if ( covariantReturnMethodMap . Any ( m => m . OverridenMethod . EqualAnyBaseDefinitionTo ( method ) ) )
423- continue ;
424-
425422 if ( method . IsVisibleAndVirtual ( ) && ! _ignores . Contains ( method . Name ) )
423+ {
424+ var covariantReturnMethod = covariantReturnMethods . FirstOrDefault ( m => m . OverridenMethod . IsSameBaseDefinition ( method ) ) ;
425+ var overriden = covariantReturnMethod . OverridenMethod ;
426+ if ( overriden != null )
427+ {
428+ // if method is the base definition of the overriden method, the CovariantReturnMethod is not in serviceType, so we need to add CovariantReturnMethod to implType.
429+ // otherwise, the CovariantReturnMethod is also in serviceType, which will be added to implType next for-loops.
430+ if ( overriden . GetBaseDefinition ( ) == method )
431+ {
432+ DefineClassMethod ( covariantReturnMethod . CovariantReturnMethod , implType , typeDesc ) ;
433+ }
434+
435+ // covariantReturnMethod is found, do not add method to implType.
436+ continue ;
437+ }
438+
426439 DefineClassMethod ( method , implType , typeDesc ) ;
440+ }
427441 }
428442 foreach ( var item in additionalInterfaces )
429443 {
@@ -448,7 +462,7 @@ internal static MethodBuilder DefineExplicitMethod(MethodInfo method, Type implT
448462 return methodBuilder ;
449463 }
450464
451- internal static MethodBuilder DefineClassMethod ( MethodInfo method , Type implType , TypeDesc typeDesc , bool isNewSlot = false )
465+ internal static MethodBuilder DefineClassMethod ( MethodInfo method , Type implType , TypeDesc typeDesc , MethodInfo covariantReturnMethod = null , bool isNewSlot = false )
452466 {
453467 var attributes = OverrideMethodAttributes ;
454468
@@ -472,17 +486,31 @@ internal static MethodBuilder DefineClassMethod(MethodInfo method, Type implType
472486 attributes |= MethodAttributes . NewSlot ;
473487 }
474488
475- var methodBuilder = DefineMethod ( method , method . Name , attributes , implType , typeDesc ) ;
489+ var methodBuilder = DefineMethod ( method , method . Name , attributes , implType , typeDesc , covariantReturnMethod ) ;
476490 return methodBuilder ;
477491 }
478492
479- // NOTE: when a covariant return method is handling:
480- // For class proxy: We just define the covariant return methods in the implementation type like normal methods, the CLR will handle the propagation. (in this case covariantReturnMethod is null)
481- // For interface proxy: We need to use the covariant return methods as the interface methods' implementation. (in this case covariantReturnMethod is not null)
482493 private static MethodBuilder DefineMethod ( MethodInfo method , string name , MethodAttributes attributes , Type implType , TypeDesc typeDesc , MethodInfo covariantReturnMethod = null )
483494 {
484495 var methodBuilder = typeDesc . Builder . DefineMethod ( name , attributes , method . CallingConvention , method . ReturnType , method . GetParameterTypes ( ) ) ;
485496
497+ GenericParameterUtils . DefineGenericParameter ( method , methodBuilder ) ;
498+
499+ //define method attributes
500+ methodBuilder . SetCustomAttribute ( CustomAttributeBuilderUtils . DefineCustomAttribute ( typeof ( DynamicallyAttribute ) ) ) ;
501+
502+ //inherit targetMethod's attribute
503+ foreach ( var customAttributeData in method . CustomAttributes )
504+ {
505+ if ( customAttributeData . AttributeType == AspectCore . Extensions . MethodInfoExtensions . PreserveBaseOverridesAttribute )
506+ continue ;
507+
508+ methodBuilder . SetCustomAttribute ( CustomAttributeBuilderUtils . DefineCustomAttribute ( customAttributeData ) ) ;
509+ }
510+
511+ //define parameters
512+ ParameterBuilderUtils . DefineParameters ( method , methodBuilder ) ;
513+
486514 var implementationMethod = covariantReturnMethod ?? implType . GetTypeInfo ( ) . GetMethodBySignature ( method ) ;
487515 if ( implementationMethod == null )
488516 {
@@ -514,23 +542,6 @@ private static MethodBuilder DefineMethod(MethodInfo method, string name, Method
514542 }
515543 }
516544
517- GenericParameterUtils . DefineGenericParameter ( method , methodBuilder ) ;
518-
519- //define method attributes
520- methodBuilder . SetCustomAttribute ( CustomAttributeBuilderUtils . DefineCustomAttribute ( typeof ( DynamicallyAttribute ) ) ) ;
521-
522- //inherit targetMethod's attribute
523- foreach ( var customAttributeData in method . CustomAttributes )
524- {
525- if ( customAttributeData . AttributeType == AspectCore . Extensions . MethodInfoExtensions . PreserveBaseOverridesAttribute )
526- continue ;
527-
528- methodBuilder . SetCustomAttribute ( CustomAttributeBuilderUtils . DefineCustomAttribute ( customAttributeData ) ) ;
529- }
530-
531- //define parameters
532- ParameterBuilderUtils . DefineParameters ( method , methodBuilder ) ;
533-
534545 if ( method . IsNonAspect ( ) )
535546 {
536547 EmitMethodBody ( ) ;
@@ -760,13 +771,13 @@ private class PropertyBuilderUtils
760771 {
761772 public static void DefineInterfaceProxyProperties ( Type interfaceType , Type implType , Type [ ] additionalInterfaces , TypeDesc typeDesc )
762773 {
763- var covariantReturnMethodMap = implType . GetCovariantReturnMethods ( ) ;
774+ var covariantReturnMethods = implType . GetCovariantReturnMethods ( ) ;
764775
765776 foreach ( var property in interfaceType . GetTypeInfo ( ) . DeclaredProperties )
766777 {
767778 var builder = DefineInterfaceProxyProperty ( property , property . Name , implType , typeDesc ) ;
768779 var covariantReturnGetter = property . CanRead
769- ? covariantReturnMethodMap . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( property . GetMethod ) ) . CovariantReturnMethod
780+ ? covariantReturnMethods . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( property . GetMethod ) ) . CovariantReturnMethod
770781 : null ;
771782 DefineInterfacePropertyMethod ( builder , property , implType , typeDesc , covariantReturnGetter ) ;
772783 }
@@ -776,7 +787,7 @@ public static void DefineInterfaceProxyProperties(Type interfaceType, Type implT
776787 {
777788 var builder = DefineInterfaceProxyProperty ( property , property . GetDisplayName ( ) , implType , typeDesc ) ;
778789 var covariantReturnGetter = property . CanRead
779- ? covariantReturnMethodMap . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( property . GetMethod ) ) . CovariantReturnMethod
790+ ? covariantReturnMethods . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( property . GetMethod ) ) . CovariantReturnMethod
780791 : null ;
781792 DefineExplicitPropertyMethod ( builder , property , implType , typeDesc , covariantReturnGetter ) ;
782793 }
@@ -785,31 +796,20 @@ public static void DefineInterfaceProxyProperties(Type interfaceType, Type implT
785796
786797 internal static void DefineClassProxyProperties ( Type serviceType , Type implType , Type [ ] additionalInterfaces , TypeDesc typeDesc )
787798 {
788- var covariantReturnMethodMap = implType . GetCovariantReturnMethods ( ) ;
799+ var covariantReturnMethods = implType . GetCovariantReturnMethods ( ) ;
789800
790801 foreach ( var property in serviceType . GetTypeInfo ( ) . GetProperties ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ) )
791802 {
792- var isNewSlot = false ;
803+ MethodInfo covariantReturnGetter = null ;
793804
794805 if ( property . CanRead )
795806 {
796- // skip if the property is overridden by a covariant return method
797- if ( covariantReturnMethodMap . Any ( m => m . CovariantReturnMethod . EqualAnyBaseDefinitionTo ( property . GetMethod )
798- && m . OverridenMethod . ReturnType == property . PropertyType ) )
799- continue ;
800-
801- if ( covariantReturnMethodMap . Any ( m => m . CovariantReturnMethod . EqualAnyBaseDefinitionTo ( property . GetMethod )
802- && m . CovariantReturnMethod . ReturnType == property . PropertyType ) )
803- {
804- // this property's getter is a covariant return method.
805- isNewSlot = true ;
806- }
807807 }
808808
809809 if ( property . IsVisibleAndVirtual ( ) )
810810 {
811811 var builder = DefineInterfaceProxyProperty ( property , property . Name , implType , typeDesc ) ;
812- DefineClassPropertyMethod ( builder , property , implType , typeDesc , isNewSlot ) ;
812+ DefineClassPropertyMethod ( builder , property , implType , typeDesc , covariantReturnGetter ) ;
813813 }
814814 }
815815 foreach ( var item in additionalInterfaces )
@@ -822,11 +822,11 @@ internal static void DefineClassProxyProperties(Type serviceType, Type implType,
822822 }
823823 }
824824
825- private static void DefineClassPropertyMethod ( PropertyBuilder propertyBuilder , PropertyInfo property , Type implType , TypeDesc typeDesc , bool isNewSlot = false )
825+ private static void DefineClassPropertyMethod ( PropertyBuilder propertyBuilder , PropertyInfo property , Type implType , TypeDesc typeDesc , MethodInfo covariantReturnGetter = null )
826826 {
827827 if ( property . CanRead )
828828 {
829- var method = MethodBuilderUtils . DefineClassMethod ( property . GetMethod , implType , typeDesc , isNewSlot ) ;
829+ var method = MethodBuilderUtils . DefineClassMethod ( property . GetMethod , implType , typeDesc , covariantReturnGetter ) ;
830830 propertyBuilder . SetGetMethod ( method ) ;
831831 }
832832 if ( property . CanWrite )
0 commit comments