11using System ;
2+ #if NET45_OR_GREATER || NETSTANDARD
3+ using System . Buffers ;
4+ #endif
25using System . Collections . Generic ;
36using System . Linq ;
47using System . Reflection ;
8+ #if NET40
9+
10+ using PolyfillsForOldDotNet . System . Buffers ;
11+ #endif
512
613using JavaScriptEngineSwitcher . Core . Utilities ;
714
@@ -113,6 +120,11 @@ public static void FixPropertyValueType(ref object value, PropertyInfo property)
113120 public static void FixArgumentTypes ( ref object [ ] argValues , ParameterInfo [ ] parameters )
114121 {
115122 int argCount = argValues . Length ;
123+ if ( argCount == 0 )
124+ {
125+ return ;
126+ }
127+
116128 int parameterCount = parameters . Length ;
117129
118130 for ( int argIndex = 0 ; argIndex < argCount ; argIndex ++ )
@@ -147,54 +159,72 @@ public static void FixArgumentTypes(ref object[] argValues, ParameterInfo[] para
147159
148160 public static MethodBase GetBestFitMethod ( MethodBase [ ] methods , object [ ] argValues )
149161 {
150- MethodWithMetadata [ ] methodCandidates = methods
151- . Select ( m => new MethodWithMetadata
152- {
153- Method = m ,
154- ParameterTypes = m . GetParameters ( )
155- . Select ( p => p . ParameterType )
156- . ToArray ( )
157- } )
158- . ToArray ( )
159- ;
160- int argCount = argValues . Length ;
161- MethodWithMetadata [ ] sameArityMethods = methodCandidates
162- . Where ( m => m . ParameterTypes . Length == argCount )
163- . ToArray ( )
164- ;
165-
166- int sameArityMethodCount = sameArityMethods . Length ;
167- if ( sameArityMethodCount == 0 )
162+ int methodCount = methods . Length ;
163+ if ( methodCount == 0 )
168164 {
169165 return null ;
170166 }
171167
172- Type [ ] argTypes = argValues
173- . Select ( a => a != null ? a . GetType ( ) : typeof ( object ) )
174- . ToArray ( )
175- ;
176- var compatibleMethods = new List < MethodWithMetadata > ( ) ;
177-
178- for ( int methodIndex = 0 ; methodIndex < sameArityMethodCount ; methodIndex ++ )
168+ if ( methodCount == 1 )
179169 {
180- MethodWithMetadata method = sameArityMethods [ methodIndex ] ;
181- ushort compatibilityScore ;
170+ MethodBase method = methods [ 0 ] ;
171+ ParameterInfo [ ] parameters = method . GetParameters ( ) ;
182172
183- if ( CompareParameterTypes ( argValues , argTypes , method . ParameterTypes , out compatibilityScore ) )
173+ MethodBase bestFitMethod = null ;
174+ if ( CompareParameterTypes ( argValues , parameters , out _ ) )
184175 {
185- method . CompatibilityScore = compatibilityScore ;
186- compatibleMethods . Add ( method ) ;
176+ bestFitMethod = method ;
187177 }
178+
179+ return bestFitMethod ;
188180 }
189181
190- int compatibleMethodCount = compatibleMethods . Count ;
191- if ( compatibleMethodCount > 0 )
182+ MethodWithMetadata [ ] compatibleMethods = null ;
183+ int compatibleMethodCount = 0 ;
184+
185+ var methodArrayPool = ArrayPool < MethodWithMetadata > . Shared ;
186+ MethodWithMetadata [ ] buffer = methodArrayPool . Rent ( methodCount ) ;
187+
188+ try
192189 {
193- if ( compatibleMethodCount == 1 )
190+ for ( int methodIndex = 0 ; methodIndex < methodCount ; methodIndex ++ )
191+ {
192+ MethodBase method = methods [ methodIndex ] ;
193+ ParameterInfo [ ] parameters = method . GetParameters ( ) ;
194+ ushort compatibilityScore ;
195+
196+ if ( CompareParameterTypes ( argValues , parameters , out compatibilityScore ) )
197+ {
198+ compatibleMethodCount ++ ;
199+
200+ int compatibleMethodIndex = compatibleMethodCount - 1 ;
201+ buffer [ compatibleMethodIndex ] = new MethodWithMetadata
202+ {
203+ Method = method ,
204+ CompatibilityScore = compatibilityScore
205+ } ;
206+ }
207+ }
208+
209+ if ( compatibleMethodCount > 0 )
194210 {
195- return compatibleMethods [ 0 ] . Method ;
211+ if ( compatibleMethodCount == 1 )
212+ {
213+ return buffer [ 0 ] . Method ;
214+ }
215+
216+ compatibleMethods = new MethodWithMetadata [ compatibleMethodCount ] ;
217+ Array . Copy ( buffer , compatibleMethods , compatibleMethodCount ) ;
196218 }
219+ }
220+ finally
221+ {
222+ bool clearArray = compatibleMethodCount > 0 ;
223+ methodArrayPool . Return ( buffer , clearArray ) ;
224+ }
197225
226+ if ( compatibleMethods != null )
227+ {
198228 MethodWithMetadata bestFitMethod = compatibleMethods
199229 . OrderByDescending ( m => m . CompatibilityScore )
200230 . First ( )
@@ -206,24 +236,29 @@ public static MethodBase GetBestFitMethod(MethodBase[] methods, object[] argValu
206236 return null ;
207237 }
208238
209- private static bool CompareParameterTypes ( object [ ] argValues , Type [ ] argTypes , Type [ ] parameterTypes ,
239+ private static bool CompareParameterTypes ( object [ ] argValues , ParameterInfo [ ] parameters ,
210240 out ushort compatibilityScore )
211241 {
212- int argValueCount = argValues . Length ;
213- int argTypeCount = argTypes . Length ;
214- int parameterCount = parameterTypes . Length ;
242+ int argCount = argValues . Length ;
243+ int parameterCount = parameters . Length ;
215244 compatibilityScore = 0 ;
216245
217- if ( argValueCount != argTypeCount || argTypeCount != parameterCount )
246+ if ( argCount != parameterCount )
218247 {
219248 return false ;
220249 }
250+ else if ( argCount == 0 )
251+ {
252+ compatibilityScore = ushort . MaxValue ;
253+ return true ;
254+ }
221255
222- for ( int argIndex = 0 ; argIndex < argValueCount ; argIndex ++ )
256+ for ( int argIndex = 0 ; argIndex < argCount ; argIndex ++ )
223257 {
224258 object argValue = argValues [ argIndex ] ;
225- Type argType = argTypes [ argIndex ] ;
226- Type parameterType = parameterTypes [ argIndex ] ;
259+ Type argType = argValue != null ? argValue . GetType ( ) : typeof ( object ) ;
260+ ParameterInfo parameter = parameters [ argIndex ] ;
261+ Type parameterType = parameter . ParameterType ;
227262
228263 if ( argType == parameterType )
229264 {
@@ -239,8 +274,6 @@ private static bool CompareParameterTypes(object[] argValues, Type[] argTypes, T
239274 {
240275 return false ;
241276 }
242-
243- continue ;
244277 }
245278 }
246279
@@ -297,12 +330,6 @@ public MethodBase Method
297330 set ;
298331 }
299332
300- public Type [ ] ParameterTypes
301- {
302- get ;
303- set ;
304- }
305-
306333 /// TODO: In future will need to change type to <c>double</c>
307334 public ushort CompatibilityScore
308335 {
0 commit comments