@@ -30,7 +30,7 @@ partial class RequestBuilderImplementation : IRequestBuilder
3030 HttpMethod . Head
3131 } ;
3232 readonly Dictionary < string , List < RestMethodInfo > > interfaceHttpMethods ;
33- readonly ConcurrentDictionary < int , Func < HttpClient , object [ ] , object > > restResultFuncForMethodsMap ;
33+ readonly ConcurrentDictionary < RestMethodKey , Func < HttpClient , object [ ] , object > > restResultFuncForMethodsMap ;
3434 readonly IContentSerializer serializer ;
3535 readonly RefitSettings settings ;
3636 public Type TargetType { get ; }
@@ -41,7 +41,7 @@ public RequestBuilderImplementation(Type refitInterfaceType, RefitSettings refit
4141
4242 settings = refitSettings ?? new RefitSettings ( ) ;
4343 serializer = settings . ContentSerializer ;
44- restResultFuncForMethodsMap = new ConcurrentDictionary < int , Func < HttpClient , object [ ] , object > > ( ) ;
44+ restResultFuncForMethodsMap = new ConcurrentDictionary < RestMethodKey , Func < HttpClient , object [ ] , object > > ( ) ;
4545
4646 if ( refitInterfaceType == null || ! refitInterfaceType . GetTypeInfo ( ) . IsInterface )
4747 {
@@ -139,29 +139,7 @@ RestMethodInfo CloseGenericMethodIfNeeded(RestMethodInfo restMethodInfo, Type[]
139139
140140 public Func < HttpClient , object [ ] , object > BuildRestResultFuncForMethod ( string methodName , Type [ ] parameterTypes = null , Type [ ] genericArgumentTypes = null )
141141 {
142- /* Build a unique key for this specific rest method, by combining
143- * all the necessary info: method name, parameter types and generic
144- * arguments. We're doing this work here since we can't just modify
145- * the existing interface, as that would be a breaking chance.*/
146- HashCode hashCode = default ;
147-
148- hashCode . Add ( methodName ) ;
149-
150- hashCode . Add ( parameterTypes ) ;
151- if ( ! ( parameterTypes is null ) )
152- {
153- foreach ( var type in parameterTypes )
154- hashCode . Add ( type ) ;
155- }
156-
157- hashCode . Add ( genericArgumentTypes ) ;
158- if ( ! ( genericArgumentTypes is null ) )
159- {
160- foreach ( var type in genericArgumentTypes )
161- hashCode . Add ( type ) ;
162- }
163-
164- var key = hashCode . ToHashCode ( ) ;
142+ var key = new RestMethodKey ( methodName , parameterTypes , genericArgumentTypes ) ;
165143
166144 /* Fast path if we have already generated this specific method before: in that
167145 * case we simply get it from the cache and return it immediately.
@@ -175,8 +153,61 @@ public Func<HttpClient, object[], object> BuildRestResultFuncForMethod(string me
175153 return BuildAndAddRestResultFuncForMethod ( key , methodName , parameterTypes , genericArgumentTypes ) ;
176154 }
177155
156+ /// <summary>
157+ /// A <see langword="struct"/> acting as key for a given generated REST method.
158+ /// </summary>
159+ private readonly struct RestMethodKey : IEquatable < RestMethodKey >
160+ {
161+ private readonly string methodName ;
162+ private readonly Type [ ] parameterTypes ;
163+ private readonly Type [ ] genericArgumentTypes ;
164+
165+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
166+ internal RestMethodKey ( string methodName , Type [ ] parameterTypes , Type [ ] genericArgumentTypes )
167+ {
168+ this . methodName = methodName ;
169+ this . parameterTypes = parameterTypes ;
170+ this . genericArgumentTypes = genericArgumentTypes ;
171+ }
172+
173+ /// <inheritdoc/>
174+ public override bool Equals ( object obj )
175+ {
176+ if ( obj is null ) return false ;
177+ if ( obj . GetType ( ) != typeof ( RestMethodKey ) ) return false ;
178+
179+ return Equals ( ( RestMethodKey ) obj ) ;
180+ }
181+
182+ /// <inheritdoc/>
183+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
184+ public bool Equals ( RestMethodKey other )
185+ {
186+ return
187+ methodName == other . methodName &&
188+ parameterTypes == other . parameterTypes &&
189+ genericArgumentTypes == other . genericArgumentTypes ;
190+ }
191+
192+ /// <inheritdoc/>
193+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
194+ public override int GetHashCode ( )
195+ {
196+ HashCode hashCode = default ;
197+
198+ /* We can just compare the arrays directly since the
199+ * stubs are caching all the array instances, so we
200+ * don't need to iterate and inspect each array value. */
201+ hashCode . Add ( methodName ) ;
202+ hashCode . Add ( parameterTypes ) ;
203+ hashCode . Add ( genericArgumentTypes ) ;
204+
205+ return hashCode . ToHashCode ( ) ;
206+ }
207+ }
208+
178209 [ MethodImpl ( MethodImplOptions . NoInlining ) ]
179- private Func < HttpClient , object [ ] , object > BuildAndAddRestResultFuncForMethod ( int key , string methodName , Type [ ] parameterTypes = null , Type [ ] genericArgumentTypes = null )
210+ private Func < HttpClient , object [ ] , object > BuildAndAddRestResultFuncForMethod ( RestMethodKey key , string methodName , Type [ ] parameterTypes = null , Type [ ] genericArgumentTypes = null )
180211 {
181212 return restResultFuncForMethodsMap . GetOrAdd ( key , _ =>
182213 {
0 commit comments