|
6 | 6 | using System.Linq; |
7 | 7 | using System.Reflection; |
8 | 8 | using System.Reflection.Emit; |
| 9 | +using System.Runtime.CompilerServices; |
9 | 10 | using System.Threading; |
10 | 11 | using System.Threading.Tasks; |
11 | 12 | using AspectCore.DynamicProxy; |
@@ -163,6 +164,29 @@ private Type CreateClassProxyInternal(string name, Type serviceType, Type implTy |
163 | 164 | return typeDesc.Compile(); |
164 | 165 | } |
165 | 166 |
|
| 167 | + // key: covariant return method |
| 168 | + // value: interface method declarations |
| 169 | + internal static IReadOnlyDictionary<MethodInfo, HashSet<MethodInfo>> GetCovariantReturnMethodMap(Type implType) |
| 170 | + { |
| 171 | + var result = new Dictionary<MethodInfo, HashSet<MethodInfo>>(); |
| 172 | + // No PreserveBaseOverridesAttribute means that the runtime does not support covariant return types. |
| 173 | + if (AspectCore.Extensions.MethodInfoExtensions.PreserveBaseOverridesAttribute is null) |
| 174 | + return result; |
| 175 | + |
| 176 | + var covariantReturnMethods = implType |
| 177 | + .GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) |
| 178 | + .Where(m => m.IsPreserveBaseOverride(true)) |
| 179 | + .ToHashSet(); |
| 180 | + |
| 181 | + foreach (var method in covariantReturnMethods) |
| 182 | + { |
| 183 | + var interfaceDeclarations = method.GetInterfaceDeclarations().ToHashSet(); |
| 184 | + result[method] = interfaceDeclarations; |
| 185 | + } |
| 186 | + |
| 187 | + return result; |
| 188 | + } |
| 189 | + |
166 | 190 | private class ProxyNameUtils |
167 | 191 | { |
168 | 192 | private readonly Dictionary<string, ProxyNameIndex> _indexes = new Dictionary<string, ProxyNameIndex>(); |
@@ -461,7 +485,10 @@ internal static MethodBuilder DefineClassMethod(MethodInfo method, Type implType |
461 | 485 | var methodBuilder = DefineMethod(method, method.Name, attributes, implType, typeDesc); |
462 | 486 | return methodBuilder; |
463 | 487 | } |
464 | | - |
| 488 | + |
| 489 | + // NOTE: when a covariant return method is handling: |
| 490 | + // 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) |
| 491 | + // For interface proxy: We need to use the covariant return methods as the interface methods' implementation. (in this case covariantReturnMethod is not null) |
465 | 492 | private static MethodBuilder DefineMethod(MethodInfo method, string name, MethodAttributes attributes, Type implType, TypeDesc typeDesc, MethodInfo covariantReturnMethod = null) |
466 | 493 | { |
467 | 494 | var implementationMethod = covariantReturnMethod ?? implType.GetTypeInfo().GetMethodBySignature(method); |
|
0 commit comments