11using System ;
2+ using System . Collections . Generic ;
23using System . Linq ;
34using System . Reflection ;
45
@@ -84,9 +85,8 @@ public static void FixArgumentTypes(ref object[] argValues, ParameterInfo[] para
8485
8586 public static MethodBase GetBestFitMethod ( MethodBase [ ] methods , object [ ] argValues )
8687 {
87- int argCount = argValues . Length ;
88- var methodCandidates = methods
89- . Select ( m => new
88+ MethodWithMetadata [ ] methodCandidates = methods
89+ . Select ( m => new MethodWithMetadata
9090 {
9191 Method = m ,
9292 ParameterTypes = m . GetParameters ( )
@@ -95,12 +95,14 @@ public static MethodBase GetBestFitMethod(MethodBase[] methods, object[] argValu
9595 } )
9696 . ToArray ( )
9797 ;
98-
99- var methodsWithSameArity = methodCandidates
98+ int argCount = argValues . Length ;
99+ MethodWithMetadata [ ] sameArityMethods = methodCandidates
100100 . Where ( m => m . ParameterTypes . Length == argCount )
101101 . ToArray ( )
102102 ;
103- if ( methodsWithSameArity . Length == 0 )
103+
104+ int sameArityMethodCount = sameArityMethods . Length ;
105+ if ( sameArityMethodCount == 0 )
104106 {
105107 return null ;
106108 }
@@ -109,40 +111,46 @@ public static MethodBase GetBestFitMethod(MethodBase[] methods, object[] argValu
109111 . Select ( a => a . GetType ( ) )
110112 . ToArray ( )
111113 ;
112- var weaklyCompatibleMethods = methodsWithSameArity
113- . Where ( m => CompareParameterTypes ( argValues , argTypes , m . ParameterTypes , false ) )
114- . ToArray ( )
115- ;
114+ var compatibleMethods = new List < MethodWithMetadata > ( ) ;
116115
117- int weaklyCompatibleMethodCount = weaklyCompatibleMethods . Length ;
118- if ( weaklyCompatibleMethodCount > 0 )
116+ for ( int methodIndex = 0 ; methodIndex < sameArityMethodCount ; methodIndex ++ )
119117 {
120- if ( weaklyCompatibleMethodCount == 1 )
118+ MethodWithMetadata method = sameArityMethods [ methodIndex ] ;
119+ ushort compatibilityScore ;
120+
121+ if ( CompareParameterTypes ( argValues , argTypes , method . ParameterTypes , out compatibilityScore ) )
121122 {
122- return weaklyCompatibleMethods [ 0 ] . Method ;
123+ method . CompatibilityScore = compatibilityScore ;
124+ compatibleMethods . Add ( method ) ;
123125 }
126+ }
124127
125- var strictlyCompatibleMethods = weaklyCompatibleMethods
126- . Where ( m => CompareParameterTypes ( argValues , argTypes , m . ParameterTypes , true ) )
127- . ToArray ( )
128- ;
129- if ( strictlyCompatibleMethods . Length > 0 )
128+ int compatibleMethodCount = compatibleMethods . Count ;
129+ if ( compatibleMethodCount > 0 )
130+ {
131+ if ( compatibleMethodCount == 1 )
130132 {
131- return strictlyCompatibleMethods [ 0 ] . Method ;
133+ return compatibleMethods [ 0 ] . Method ;
132134 }
133135
134- return weaklyCompatibleMethods [ 0 ] . Method ;
136+ MethodWithMetadata bestFitMethod = compatibleMethods
137+ . OrderByDescending ( m => m . CompatibilityScore )
138+ . First ( )
139+ ;
140+
141+ return bestFitMethod . Method ;
135142 }
136143
137144 return null ;
138145 }
139146
140147 private static bool CompareParameterTypes ( object [ ] argValues , Type [ ] argTypes , Type [ ] parameterTypes ,
141- bool strictСompliance )
148+ out ushort compatibilityScore )
142149 {
143150 int argValueCount = argValues . Length ;
144151 int argTypeCount = argTypes . Length ;
145152 int parameterCount = parameterTypes . Length ;
153+ compatibilityScore = 0 ;
146154
147155 if ( argValueCount != argTypeCount || argTypeCount != parameterCount )
148156 {
@@ -155,10 +163,13 @@ private static bool CompareParameterTypes(object[] argValues, Type[] argTypes, T
155163 Type argType = argTypes [ argIndex ] ;
156164 Type parameterType = parameterTypes [ argIndex ] ;
157165
158- if ( argType != parameterType )
166+ if ( argType == parameterType )
167+ {
168+ compatibilityScore ++ ;
169+ }
170+ else
159171 {
160- if ( ! strictСompliance
161- && NumericHelpers . IsNumericType ( argType ) && NumericHelpers . IsNumericType ( parameterType ) )
172+ if ( NumericHelpers . IsNumericType ( argType ) && NumericHelpers . IsNumericType ( parameterType ) )
162173 {
163174 object convertedArgValue ;
164175
@@ -167,11 +178,6 @@ private static bool CompareParameterTypes(object[] argValues, Type[] argTypes, T
167178 return false ;
168179 }
169180
170- if ( argValue != convertedArgValue )
171- {
172- return false ;
173- }
174-
175181 continue ;
176182 }
177183
@@ -181,5 +187,27 @@ private static bool CompareParameterTypes(object[] argValues, Type[] argTypes, T
181187
182188 return true ;
183189 }
190+
191+
192+ private sealed class MethodWithMetadata
193+ {
194+ public MethodBase Method
195+ {
196+ get ;
197+ set ;
198+ }
199+
200+ public Type [ ] ParameterTypes
201+ {
202+ get ;
203+ set ;
204+ }
205+
206+ public ushort CompatibilityScore
207+ {
208+ get ;
209+ set ;
210+ }
211+ }
184212 }
185213}
0 commit comments