@@ -162,29 +162,6 @@ private Type CreateClassProxyInternal(string name, Type serviceType, Type implTy
162162 return typeDesc . Compile ( ) ;
163163 }
164164
165- // key: covariant return method
166- // value: interface method declarations
167- internal static IReadOnlyDictionary < MethodInfo , HashSet < MethodInfo > > GetCovariantReturnMethodMap ( Type implType )
168- {
169- var result = new Dictionary < MethodInfo , HashSet < MethodInfo > > ( ) ;
170- // No PreserveBaseOverridesAttribute means that the runtime does not support covariant return types.
171- if ( AspectCore . Extensions . MethodInfoExtensions . PreserveBaseOverridesAttribute is null )
172- return result ;
173-
174- var covariantReturnMethods = implType
175- . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance )
176- . Where ( m => m . IsPreserveBaseOverride ( true ) )
177- . ToHashSet ( ) ;
178-
179- foreach ( var method in covariantReturnMethods )
180- {
181- var interfaceDeclarations = method . GetInterfaceDeclarations ( ) . ToHashSet ( ) ;
182- result [ method ] = interfaceDeclarations ;
183- }
184-
185- return result ;
186- }
187-
188165 private class ProxyNameUtils
189166 {
190167 private readonly Dictionary < string , ProxyNameIndex > _indexes = new Dictionary < string , ProxyNameIndex > ( ) ;
@@ -415,26 +392,36 @@ internal static MethodBuilder DefineInterfaceImplMethod(MethodInfo method, TypeB
415392
416393 internal static void DefineInterfaceProxyMethods ( Type interfaceType , Type targetType , Type [ ] additionalInterfaces , TypeDesc typeDesc )
417394 {
418- var covariantReturnMethodMap = GetCovariantReturnMethodMap ( targetType ) ;
395+ var covariantReturnMethodMap = targetType . GetCovariantReturnMethods ( ) ;
419396 foreach ( var method in interfaceType . GetTypeInfo ( ) . DeclaredMethods . Where ( x => ! x . IsPropertyBinding ( ) ) )
420397 {
421- var covariantReturnMethod = covariantReturnMethodMap . FirstOrDefault ( m => m . Value . Contains ( method ) ) . Key ;
398+ var covariantReturnMethod = covariantReturnMethodMap
399+ . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( method ) )
400+ . CovariantReturnMethod ;
401+
422402 DefineInterfaceMethod ( method , targetType , typeDesc , covariantReturnMethod ) ;
423403 }
424404 foreach ( var item in additionalInterfaces )
425405 {
426406 foreach ( var method in item . GetTypeInfo ( ) . DeclaredMethods . Where ( x => ! x . IsPropertyBinding ( ) ) )
427407 {
428- var covariantReturnMethod = covariantReturnMethodMap . FirstOrDefault ( m => m . Value . Contains ( method ) ) . Key ;
408+ var covariantReturnMethod = covariantReturnMethodMap
409+ . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( method ) )
410+ . CovariantReturnMethod ;
411+
429412 DefineExplicitMethod ( method , targetType , typeDesc , covariantReturnMethod ) ;
430413 }
431414 }
432415 }
433416
434417 internal static void DefineClassProxyMethods ( Type serviceType , Type implType , Type [ ] additionalInterfaces , TypeDesc typeDesc )
435418 {
419+ var covariantReturnMethodMap = implType . GetCovariantReturnMethods ( ) ;
436420 foreach ( var method in serviceType . GetTypeInfo ( ) . GetMethods ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ) . Where ( x => ! x . IsPropertyBinding ( ) ) )
437421 {
422+ if ( covariantReturnMethodMap . Any ( m => m . OverridenMethod . EqualAnyBaseDefinitionTo ( method ) ) )
423+ continue ;
424+
438425 if ( method . IsVisibleAndVirtual ( ) && ! _ignores . Contains ( method . Name ) )
439426 DefineClassMethod ( method , implType , typeDesc ) ;
440427 }
@@ -461,7 +448,7 @@ internal static MethodBuilder DefineExplicitMethod(MethodInfo method, Type implT
461448 return methodBuilder ;
462449 }
463450
464- internal static MethodBuilder DefineClassMethod ( MethodInfo method , Type implType , TypeDesc typeDesc )
451+ internal static MethodBuilder DefineClassMethod ( MethodInfo method , Type implType , TypeDesc typeDesc , bool isNewSlot = false )
465452 {
466453 var attributes = OverrideMethodAttributes ;
467454
@@ -480,15 +467,22 @@ internal static MethodBuilder DefineClassMethod(MethodInfo method, Type implType
480467 attributes |= MethodAttributes . FamORAssem ;
481468 }
482469
470+ if ( isNewSlot )
471+ {
472+ attributes |= MethodAttributes . NewSlot ;
473+ }
474+
483475 var methodBuilder = DefineMethod ( method , method . Name , attributes , implType , typeDesc ) ;
484476 return methodBuilder ;
485477 }
486-
478+
487479 // NOTE: when a covariant return method is handling:
488480 // 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)
489481 // For interface proxy: We need to use the covariant return methods as the interface methods' implementation. (in this case covariantReturnMethod is not null)
490482 private static MethodBuilder DefineMethod ( MethodInfo method , string name , MethodAttributes attributes , Type implType , TypeDesc typeDesc , MethodInfo covariantReturnMethod = null )
491483 {
484+ var methodBuilder = typeDesc . Builder . DefineMethod ( name , attributes , method . CallingConvention , method . ReturnType , method . GetParameterTypes ( ) ) ;
485+
492486 var implementationMethod = covariantReturnMethod ?? implType . GetTypeInfo ( ) . GetMethodBySignature ( method ) ;
493487 if ( implementationMethod == null )
494488 {
@@ -520,20 +514,6 @@ private static MethodBuilder DefineMethod(MethodInfo method, string name, Method
520514 }
521515 }
522516
523- // NOTE: both covariant return method and its corresponding overridden method should be defined with NewSlot attribute.
524- if ( method . IsPreserveBaseOverride ( true ) )
525- {
526- // PreserveBaseOverridesAttribute is used to indicate that the method is a covariant return method.
527- attributes |= MethodAttributes . NewSlot ;
528- }
529- else if ( implementationMethod . Attributes . HasFlag ( MethodAttributes . NewSlot ) && implementationMethod . IsOverriden ( ) )
530- {
531- // an overridden method with NewSlot attribute is a method overriden by a covariant return method.
532- attributes |= MethodAttributes . NewSlot ;
533- }
534-
535- var methodBuilder = typeDesc . Builder . DefineMethod ( name , attributes , method . CallingConvention , method . ReturnType , method . GetParameterTypes ( ) ) ;
536-
537517 GenericParameterUtils . DefineGenericParameter ( method , methodBuilder ) ;
538518
539519 //define method attributes
@@ -542,6 +522,9 @@ private static MethodBuilder DefineMethod(MethodInfo method, string name, Method
542522 //inherit targetMethod's attribute
543523 foreach ( var customAttributeData in method . CustomAttributes )
544524 {
525+ if ( customAttributeData . AttributeType == AspectCore . Extensions . MethodInfoExtensions . PreserveBaseOverridesAttribute )
526+ continue ;
527+
545528 methodBuilder . SetCustomAttribute ( CustomAttributeBuilderUtils . DefineCustomAttribute ( customAttributeData ) ) ;
546529 }
547530
@@ -777,13 +760,13 @@ private class PropertyBuilderUtils
777760 {
778761 public static void DefineInterfaceProxyProperties ( Type interfaceType , Type implType , Type [ ] additionalInterfaces , TypeDesc typeDesc )
779762 {
780- var covariantReturnMethodMap = GetCovariantReturnMethodMap ( implType ) ;
763+ var covariantReturnMethodMap = implType . GetCovariantReturnMethods ( ) ;
781764
782765 foreach ( var property in interfaceType . GetTypeInfo ( ) . DeclaredProperties )
783766 {
784767 var builder = DefineInterfaceProxyProperty ( property , property . Name , implType , typeDesc ) ;
785768 var covariantReturnGetter = property . CanRead
786- ? covariantReturnMethodMap . FirstOrDefault ( m => m . Value . Contains ( property . GetMethod ) ) . Key
769+ ? covariantReturnMethodMap . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( property . GetMethod ) ) . CovariantReturnMethod
787770 : null ;
788771 DefineInterfacePropertyMethod ( builder , property , implType , typeDesc , covariantReturnGetter ) ;
789772 }
@@ -793,7 +776,7 @@ public static void DefineInterfaceProxyProperties(Type interfaceType, Type implT
793776 {
794777 var builder = DefineInterfaceProxyProperty ( property , property . GetDisplayName ( ) , implType , typeDesc ) ;
795778 var covariantReturnGetter = property . CanRead
796- ? covariantReturnMethodMap . FirstOrDefault ( m => m . Value . Contains ( property . GetMethod ) ) . Key
779+ ? covariantReturnMethodMap . FirstOrDefault ( m => m . InterfaceDeclarations . Contains ( property . GetMethod ) ) . CovariantReturnMethod
797780 : null ;
798781 DefineExplicitPropertyMethod ( builder , property , implType , typeDesc , covariantReturnGetter ) ;
799782 }
@@ -802,12 +785,31 @@ public static void DefineInterfaceProxyProperties(Type interfaceType, Type implT
802785
803786 internal static void DefineClassProxyProperties ( Type serviceType , Type implType , Type [ ] additionalInterfaces , TypeDesc typeDesc )
804787 {
788+ var covariantReturnMethodMap = implType . GetCovariantReturnMethods ( ) ;
789+
805790 foreach ( var property in serviceType . GetTypeInfo ( ) . GetProperties ( BindingFlags . Public | BindingFlags . NonPublic | BindingFlags . Instance ) )
806791 {
792+ var isNewSlot = false ;
793+
794+ if ( property . CanRead )
795+ {
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+ }
807+ }
808+
807809 if ( property . IsVisibleAndVirtual ( ) )
808810 {
809811 var builder = DefineInterfaceProxyProperty ( property , property . Name , implType , typeDesc ) ;
810- DefineClassPropertyMethod ( builder , property , implType , typeDesc ) ;
812+ DefineClassPropertyMethod ( builder , property , implType , typeDesc , isNewSlot ) ;
811813 }
812814 }
813815 foreach ( var item in additionalInterfaces )
@@ -820,11 +822,11 @@ internal static void DefineClassProxyProperties(Type serviceType, Type implType,
820822 }
821823 }
822824
823- private static void DefineClassPropertyMethod ( PropertyBuilder propertyBuilder , PropertyInfo property , Type implType , TypeDesc typeDesc )
825+ private static void DefineClassPropertyMethod ( PropertyBuilder propertyBuilder , PropertyInfo property , Type implType , TypeDesc typeDesc , bool isNewSlot = false )
824826 {
825827 if ( property . CanRead )
826828 {
827- var method = MethodBuilderUtils . DefineClassMethod ( property . GetMethod , implType , typeDesc ) ;
829+ var method = MethodBuilderUtils . DefineClassMethod ( property . GetMethod , implType , typeDesc , isNewSlot ) ;
828830 propertyBuilder . SetGetMethod ( method ) ;
829831 }
830832 if ( property . CanWrite )
@@ -1133,13 +1135,13 @@ internal static void DefineGenericParameter(Type targetType, TypeBuilder typeBui
11331135 }
11341136 }
11351137
1136- internal static void DefineGenericParameter ( MethodInfo tergetMethod , MethodBuilder methodBuilder )
1138+ internal static void DefineGenericParameter ( MethodInfo targetMethod , MethodBuilder methodBuilder )
11371139 {
1138- if ( ! tergetMethod . IsGenericMethod )
1140+ if ( ! targetMethod . IsGenericMethod )
11391141 {
11401142 return ;
11411143 }
1142- var genericArguments = tergetMethod . GetGenericArguments ( ) . Select ( t => t . GetTypeInfo ( ) ) . ToArray ( ) ;
1144+ var genericArguments = targetMethod . GetGenericArguments ( ) . Select ( t => t . GetTypeInfo ( ) ) . ToArray ( ) ;
11431145 var genericArgumentsBuilders = methodBuilder . DefineGenericParameters ( genericArguments . Select ( a => a . Name ) . ToArray ( ) ) ;
11441146 for ( var index = 0 ; index < genericArguments . Length ; index ++ )
11451147 {
0 commit comments