1414
1515namespace AspectCore . Utils
1616{
17- internal class ProxyGeneratorUtils
17+ internal partial class ProxyGeneratorUtils
1818 {
1919 private const string ProxyNameSpace = "AspectCore.DynamicGenerated" ;
2020 private const string ProxyAssemblyName = "AspectCore.DynamicProxy.Generator" ;
@@ -392,15 +392,18 @@ 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 = GetCovariantReturnMethodMap ( targetType ) ;
395396 foreach ( var method in interfaceType . GetTypeInfo ( ) . DeclaredMethods . Where ( x => ! x . IsPropertyBinding ( ) ) )
396397 {
397- DefineInterfaceMethod ( method , targetType , typeDesc ) ;
398+ var covariantReturnMethod = covariantReturnMethodMap . FirstOrDefault ( m => m . Value . Contains ( method ) ) . Key ;
399+ DefineInterfaceMethod ( method , targetType , typeDesc , covariantReturnMethod ) ;
398400 }
399401 foreach ( var item in additionalInterfaces )
400402 {
401403 foreach ( var method in item . GetTypeInfo ( ) . DeclaredMethods . Where ( x => ! x . IsPropertyBinding ( ) ) )
402404 {
403- DefineExplicitMethod ( method , targetType , typeDesc ) ;
405+ var covariantReturnMethod = covariantReturnMethodMap . FirstOrDefault ( m => m . Value . Contains ( method ) ) . Key ;
406+ DefineExplicitMethod ( method , targetType , typeDesc , covariantReturnMethod ) ;
404407 }
405408 }
406409 }
@@ -421,16 +424,16 @@ internal static void DefineClassProxyMethods(Type serviceType, Type implType, Ty
421424 }
422425 }
423426
424- internal static MethodBuilder DefineInterfaceMethod ( MethodInfo method , Type implType , TypeDesc typeDesc )
427+ internal static MethodBuilder DefineInterfaceMethod ( MethodInfo method , Type implType , TypeDesc typeDesc , MethodInfo covariantReturnMethod = null )
425428 {
426- var methodBuilder = DefineMethod ( method , method . Name , InterfaceMethodAttributes , implType , typeDesc ) ;
429+ var methodBuilder = DefineMethod ( method , method . Name , InterfaceMethodAttributes , implType , typeDesc , covariantReturnMethod ) ;
427430 typeDesc . Builder . DefineMethodOverride ( methodBuilder , method ) ;
428431 return methodBuilder ;
429432 }
430433
431- internal static MethodBuilder DefineExplicitMethod ( MethodInfo method , Type implType , TypeDesc typeDesc )
434+ internal static MethodBuilder DefineExplicitMethod ( MethodInfo method , Type implType , TypeDesc typeDesc , MethodInfo covariantReturnMethod = null )
432435 {
433- var methodBuilder = DefineMethod ( method , method . GetName ( ) , ExplicitMethodAttributes , implType , typeDesc ) ;
436+ var methodBuilder = DefineMethod ( method , method . GetName ( ) , ExplicitMethodAttributes , implType , typeDesc , covariantReturnMethod ) ;
434437 typeDesc . Builder . DefineMethodOverride ( methodBuilder , method ) ;
435438 return methodBuilder ;
436439 }
@@ -454,6 +457,7 @@ internal static MethodBuilder DefineClassMethod(MethodInfo method, Type implType
454457 attributes |= MethodAttributes . FamORAssem ;
455458 }
456459
460+ // NewSlot is required for covariant return types.
457461 if ( method . Attributes . HasFlag ( MethodAttributes . NewSlot ) )
458462 {
459463 attributes |= MethodAttributes . NewSlot ;
@@ -463,7 +467,7 @@ internal static MethodBuilder DefineClassMethod(MethodInfo method, Type implType
463467 return methodBuilder ;
464468 }
465469
466- private static MethodBuilder DefineMethod ( MethodInfo method , string name , MethodAttributes attributes , Type implType , TypeDesc typeDesc )
470+ private static MethodBuilder DefineMethod ( MethodInfo method , string name , MethodAttributes attributes , Type implType , TypeDesc typeDesc , MethodInfo covariantReturnMethod = null )
467471 {
468472 var methodBuilder = typeDesc . Builder . DefineMethod ( name , attributes , method . CallingConvention , method . ReturnType , method . GetParameterTypes ( ) ) ;
469473
@@ -475,16 +479,13 @@ private static MethodBuilder DefineMethod(MethodInfo method, string name, Method
475479 //inherit targetMethod's attribute
476480 foreach ( var customAttributeData in method . CustomAttributes )
477481 {
478- if ( customAttributeData . AttributeType . Name == "PreserveBaseOverridesAttribute" )
479- continue ; // Skip PreserveBaseOverridesAttribute as it is not needed in dynamic proxy generation.
480-
481482 methodBuilder . SetCustomAttribute ( CustomAttributeBuilderUtils . DefineCustomAttribute ( customAttributeData ) ) ;
482483 }
483484
484485 //define paramters
485486 ParameterBuilderUtils . DefineParameters ( method , methodBuilder ) ;
486487
487- var implementationMethod = implType . GetTypeInfo ( ) . GetMethodBySignature ( method ) ;
488+ var implementationMethod = covariantReturnMethod ?? implType . GetTypeInfo ( ) . GetMethodBySignature ( method ) ;
488489 if ( implementationMethod == null )
489490 {
490491 var interfaces = implType . GetInterfaces ( ) ;
@@ -616,7 +617,7 @@ void EmitProxyMethodBody()
616617 ilGen . Emit ( OpCodes . Callvirt , MethodUtils . CreateAspectActivator ) ;
617618 ilGen . Emit ( OpCodes . Ldloc , activatorContext ) ;
618619
619- EmitReturnVaule ( ilGen ) ;
620+ EmitReturnValue ( ilGen ) ;
620621
621622 if ( method . ReturnType != typeof ( void ) )
622623 {
@@ -707,7 +708,7 @@ void EmitInitializeMetaData(ILGenerator ilGen)
707708 }
708709 }
709710
710- void EmitReturnVaule ( ILGenerator ilGen )
711+ void EmitReturnValue ( ILGenerator ilGen )
711712 {
712713 if ( method . ReturnType == typeof ( void ) )
713714 {
@@ -744,17 +745,25 @@ private class PropertyBuilderUtils
744745 {
745746 public static void DefineInterfaceProxyProperties ( Type interfaceType , Type implType , Type [ ] additionalInterfaces , TypeDesc typeDesc )
746747 {
748+ var covariantReturnMethodMap = GetCovariantReturnMethodMap ( implType ) ;
749+
747750 foreach ( var property in interfaceType . GetTypeInfo ( ) . DeclaredProperties )
748751 {
749752 var builder = DefineInterfaceProxyProperty ( property , property . Name , implType , typeDesc ) ;
750- DefineInterfacePropertyMethod ( builder , property , implType , typeDesc ) ;
753+ var covariantReturnGetter = property . CanRead
754+ ? covariantReturnMethodMap . FirstOrDefault ( m => m . Value . Contains ( property . GetMethod ) ) . Key
755+ : null ;
756+ DefineInterfacePropertyMethod ( builder , property , implType , typeDesc , covariantReturnGetter ) ;
751757 }
752758 foreach ( var item in additionalInterfaces )
753759 {
754760 foreach ( var property in item . GetTypeInfo ( ) . DeclaredProperties )
755761 {
756762 var builder = DefineInterfaceProxyProperty ( property , property . GetDisplayName ( ) , implType , typeDesc ) ;
757- DefineExplicitPropertyMethod ( builder , property , implType , typeDesc ) ;
763+ var covariantReturnGetter = property . CanRead
764+ ? covariantReturnMethodMap . FirstOrDefault ( m => m . Value . Contains ( property . GetMethod ) ) . Key
765+ : null ;
766+ DefineExplicitPropertyMethod ( builder , property , implType , typeDesc , covariantReturnGetter ) ;
758767 }
759768 }
760769 }
@@ -793,11 +802,11 @@ private static void DefineClassPropertyMethod(PropertyBuilder propertyBuilder, P
793802 }
794803 }
795804
796- private static void DefineInterfacePropertyMethod ( PropertyBuilder propertyBuilder , PropertyInfo property , Type implType , TypeDesc typeDesc )
805+ private static void DefineInterfacePropertyMethod ( PropertyBuilder propertyBuilder , PropertyInfo property , Type implType , TypeDesc typeDesc , MethodInfo covariantReturnGetter = null )
797806 {
798807 if ( property . CanRead )
799808 {
800- var method = MethodBuilderUtils . DefineInterfaceMethod ( property . GetMethod , implType , typeDesc ) ;
809+ var method = MethodBuilderUtils . DefineInterfaceMethod ( property . GetMethod , implType , typeDesc , covariantReturnGetter ) ;
801810 propertyBuilder . SetGetMethod ( method ) ;
802811 }
803812 if ( property . CanWrite )
@@ -807,11 +816,11 @@ private static void DefineInterfacePropertyMethod(PropertyBuilder propertyBuilde
807816 }
808817 }
809818
810- private static void DefineExplicitPropertyMethod ( PropertyBuilder propertyBuilder , PropertyInfo property , Type implType , TypeDesc typeDesc )
819+ private static void DefineExplicitPropertyMethod ( PropertyBuilder propertyBuilder , PropertyInfo property , Type implType , TypeDesc typeDesc , MethodInfo covariantReturnGetter = null )
811820 {
812821 if ( property . CanRead )
813822 {
814- var method = MethodBuilderUtils . DefineExplicitMethod ( property . GetMethod , implType , typeDesc ) ;
823+ var method = MethodBuilderUtils . DefineExplicitMethod ( property . GetMethod , implType , typeDesc , covariantReturnGetter ) ;
815824 propertyBuilder . SetGetMethod ( method ) ;
816825 }
817826 if ( property . CanWrite )
0 commit comments