11#if NETSTANDARD1_3
22using System ;
3+ using System . Collections . Generic ;
34using System . Linq ;
45using System . Reflection ;
56
@@ -85,9 +86,8 @@ public static void FixArgumentTypes(ref object[] argValues, ParameterInfo[] para
8586
8687 public static MethodBase GetBestFitMethod ( MethodBase [ ] methods , object [ ] argValues )
8788 {
88- int argCount = argValues . Length ;
89- var methodCandidates = methods
90- . Select ( m => new
89+ MethodWithMetadata [ ] methodCandidates = methods
90+ . Select ( m => new MethodWithMetadata
9191 {
9292 Method = m ,
9393 ParameterTypes = m . GetParameters ( )
@@ -96,12 +96,14 @@ public static MethodBase GetBestFitMethod(MethodBase[] methods, object[] argValu
9696 } )
9797 . ToArray ( )
9898 ;
99-
100- var methodsWithSameArity = methodCandidates
99+ int argCount = argValues . Length ;
100+ MethodWithMetadata [ ] sameArityMethods = methodCandidates
101101 . Where ( m => m . ParameterTypes . Length == argCount )
102102 . ToArray ( )
103103 ;
104- if ( methodsWithSameArity . Length == 0 )
104+
105+ int sameArityMethodCount = sameArityMethods . Length ;
106+ if ( sameArityMethodCount == 0 )
105107 {
106108 return null ;
107109 }
@@ -110,40 +112,46 @@ public static MethodBase GetBestFitMethod(MethodBase[] methods, object[] argValu
110112 . Select ( a => a . GetType ( ) )
111113 . ToArray ( )
112114 ;
113- var weaklyCompatibleMethods = methodsWithSameArity
114- . Where ( m => CompareParameterTypes ( argValues , argTypes , m . ParameterTypes , false ) )
115- . ToArray ( )
116- ;
115+ var compatibleMethods = new List < MethodWithMetadata > ( ) ;
117116
118- int weaklyCompatibleMethodCount = weaklyCompatibleMethods . Length ;
119- if ( weaklyCompatibleMethodCount > 0 )
117+ for ( int methodIndex = 0 ; methodIndex < sameArityMethodCount ; methodIndex ++ )
120118 {
121- if ( weaklyCompatibleMethodCount == 1 )
119+ MethodWithMetadata method = sameArityMethods [ methodIndex ] ;
120+ ushort compatibilityScore ;
121+
122+ if ( CompareParameterTypes ( argValues , argTypes , method . ParameterTypes , out compatibilityScore ) )
122123 {
123- return weaklyCompatibleMethods [ 0 ] . Method ;
124+ method . CompatibilityScore = compatibilityScore ;
125+ compatibleMethods . Add ( method ) ;
124126 }
127+ }
125128
126- var strictlyCompatibleMethods = weaklyCompatibleMethods
127- . Where ( m => CompareParameterTypes ( argValues , argTypes , m . ParameterTypes , true ) )
128- . ToArray ( )
129- ;
130- if ( strictlyCompatibleMethods . Length > 0 )
129+ int compatibleMethodCount = compatibleMethods . Count ;
130+ if ( compatibleMethodCount > 0 )
131+ {
132+ if ( compatibleMethodCount == 1 )
131133 {
132- return strictlyCompatibleMethods [ 0 ] . Method ;
134+ return compatibleMethods [ 0 ] . Method ;
133135 }
134136
135- return weaklyCompatibleMethods [ 0 ] . Method ;
137+ MethodWithMetadata bestFitMethod = compatibleMethods
138+ . OrderByDescending ( m => m . CompatibilityScore )
139+ . First ( )
140+ ;
141+
142+ return bestFitMethod . Method ;
136143 }
137144
138145 return null ;
139146 }
140147
141148 private static bool CompareParameterTypes ( object [ ] argValues , Type [ ] argTypes , Type [ ] parameterTypes ,
142- bool strictСompliance )
149+ out ushort compatibilityScore )
143150 {
144151 int argValueCount = argValues . Length ;
145152 int argTypeCount = argTypes . Length ;
146153 int parameterCount = parameterTypes . Length ;
154+ compatibilityScore = 0 ;
147155
148156 if ( argValueCount != argTypeCount || argTypeCount != parameterCount )
149157 {
@@ -156,32 +164,50 @@ private static bool CompareParameterTypes(object[] argValues, Type[] argTypes, T
156164 Type argType = argTypes [ argIndex ] ;
157165 Type parameterType = parameterTypes [ argIndex ] ;
158166
159- if ( argType ! = parameterType )
167+ if ( argType = = parameterType )
160168 {
161- if ( ! strictСompliance
162- && NumericHelpers . IsNumericType ( argType ) && NumericHelpers . IsNumericType ( parameterType ) )
163- {
164- object convertedArgValue ;
165-
166- if ( ! TypeConverter . TryConvertToType ( argValue , parameterType , out convertedArgValue ) )
167- {
168- return false ;
169- }
170-
171- if ( argValue != convertedArgValue )
172- {
173- return false ;
174- }
169+ compatibilityScore ++ ;
170+ }
171+ else
172+ {
173+ // TODO: It is necessary to calculate the compatibility score based on length
174+ // of inheritance and interface implementation chains.
175+ object convertedArgValue ;
175176
176- continue ;
177+ if ( ! TypeConverter . TryConvertToType ( argValue , parameterType , out convertedArgValue ) )
178+ {
179+ return false ;
177180 }
178181
179- return false ;
182+ continue ;
180183 }
181184 }
182185
183186 return true ;
184187 }
188+
189+
190+ private sealed class MethodWithMetadata
191+ {
192+ public MethodBase Method
193+ {
194+ get ;
195+ set ;
196+ }
197+
198+ public Type [ ] ParameterTypes
199+ {
200+ get ;
201+ set ;
202+ }
203+
204+ /// TODO: In future will need to change type to <code>double</code>
205+ public ushort CompatibilityScore
206+ {
207+ get ;
208+ set ;
209+ }
210+ }
185211 }
186212}
187213#endif
0 commit comments