@@ -15,6 +15,7 @@ namespace GeneXus.Metadata
1515#endif
1616 using GeneXus . Application ;
1717 using System . Collections . Concurrent ;
18+ using System . Text ;
1819
1920 public class ClassLoader
2021 {
@@ -267,15 +268,18 @@ static public void ExecuteVoidRef(object o, string mthd, Object[] args)
267268 pm [ 0 ] = ( ( pi . Attributes & ParameterAttributes . In ) != ParameterAttributes . None ) ;
268269 pm [ 1 ] = ( ( pi . Attributes & ParameterAttributes . Out ) != ParameterAttributes . None ) ;
269270 pm [ 2 ] = pi . ParameterType . IsByRef ;
270- pms [ i ] = pm ;
271+ if ( i < pms . Length )
272+ {
273+ pms [ i ] = pm ;
274+ }
271275 }
272276 try
273277 {
274278 o . GetType ( ) . InvokeMember ( mthd , BindingFlags . InvokeMethod , null , o , args , pms , null , null ) ;
275279
276280 } catch ( MissingMethodException )
277281 {
278- throw new GxClassLoaderException ( "Method " + mi . DeclaringType . FullName + "." + mi . Name + " for " + args . Length + " parameters (" + String . Join ( "," , args ) + ") not found" ) ;
282+ throw new GxClassLoaderException ( BuildParameterMismatchErrorMessage ( mi . DeclaringType . FullName , pis , args ) ) ;
279283 }
280284 }
281285 else
@@ -292,6 +296,107 @@ static public void ExecuteVoidRef(object o, string mthd, Object[] args)
292296 throw GxClassLoaderException . ProcessException ( e ) ;
293297 }
294298 }
299+ static string BuildParameterMismatchErrorMessage ( string objectName , ParameterInfo [ ] methodParameters , object [ ] runtimeMethodParameters )
300+ {
301+ string parmInfo = GetParameterTypesString ( methodParameters ) ;
302+ string runtimeParms = GetParameterValuesString ( runtimeMethodParameters ) ;
303+ StringBuilder errorMessage = new StringBuilder ( ) ;
304+ if ( methodParameters . Length == 0 )
305+ {
306+ errorMessage . Append ( $ "The object { objectName } does not have any parameters, thus it does not match the ") ;
307+ }
308+ else if ( methodParameters . Length == 1 )
309+ {
310+ errorMessage . Append ( $ "The parm rule of { objectName } with parameter: { parmInfo } does not match the ") ;
311+ }
312+ else
313+ {
314+ errorMessage . Append ( $ "The parm rule of { objectName } with parameters: { parmInfo } does not match the ") ;
315+ }
316+
317+ if ( runtimeMethodParameters . Length == 0 )
318+ {
319+ errorMessage . Append ( $ "absence of values provided at runtime. ") ;
320+ }
321+ else if ( runtimeMethodParameters . Length == 1 )
322+ {
323+ errorMessage . Append ( $ "value provided in runtime: { runtimeParms } . ") ;
324+ }
325+ else
326+ {
327+ errorMessage . Append ( $ "values provided in runtime: { runtimeParms } . ") ;
328+ }
329+ errorMessage . Append ( $ "Please check the parm rule of the { objectName } .") ;
330+
331+ return errorMessage . ToString ( ) ;
332+ }
333+
334+ static string GetParameterValuesString ( object [ ] runtimeMethodParameters )
335+ {
336+ StringBuilder sb = new StringBuilder ( ) ;
337+ sb . Append ( '(' ) ;
338+
339+ for ( int i = 0 ; i < runtimeMethodParameters . Length ; i ++ )
340+ {
341+ object parmValue = runtimeMethodParameters [ i ] ;
342+ string parmStringValue = ( parmValue is string ) ? $ "\" { parmValue } \" " : parmValue . ToString ( ) ;
343+ sb . Append ( parmStringValue ) ;
344+ if ( i < runtimeMethodParameters . Length - 1 )
345+ {
346+ sb . Append ( ", " ) ;
347+ }
348+ }
349+ sb . Append ( ')' ) ;
350+ return sb . ToString ( ) ;
351+ }
352+
353+ static string GetParameterTypesString ( ParameterInfo [ ] parameters )
354+ {
355+ StringBuilder sb = new StringBuilder ( ) ;
356+ sb . Append ( '(' ) ;
357+
358+ for ( int i = 0 ; i < parameters . Length ; i ++ )
359+ {
360+ string parmTypeName = ParameterTypeName ( parameters [ i ] . ParameterType ) ;
361+ sb . Append ( parmTypeName ) ;
362+ if ( i < parameters . Length - 1 )
363+ {
364+ sb . Append ( ", " ) ;
365+ }
366+ }
367+ sb . Append ( ')' ) ;
368+ return sb . ToString ( ) ;
369+ }
370+
371+ static string ParameterTypeName ( Type parameterType )
372+ {
373+ Type innerType = ( parameterType . IsByRef && parameterType . GetElementType ( ) != null ) ? parameterType . GetElementType ( ) : parameterType ;
374+ if ( IsNumericType ( innerType ) )
375+ return "Numeric" ;
376+ return innerType . Name ;
377+ }
378+
379+ static bool IsNumericType ( Type type )
380+ {
381+ if ( type == typeof ( byte ) ||
382+ type == typeof ( sbyte ) ||
383+ type == typeof ( short ) ||
384+ type == typeof ( ushort ) ||
385+ type == typeof ( int ) ||
386+ type == typeof ( uint ) ||
387+ type == typeof ( long ) ||
388+ type == typeof ( ulong ) ||
389+ type == typeof ( float ) ||
390+ type == typeof ( double ) ||
391+ type == typeof ( decimal ) )
392+ {
393+ return true ;
394+ }
395+ else
396+ {
397+ return false ;
398+ }
399+ }
295400 static public void ExecuteRef ( object o , string mthd , Object [ ] args )
296401 {
297402 GXLogging . Debug ( log , "ExecuteRef '" + "class '" + o + "' mthd '" + mthd + "'" ) ;
0 commit comments