Skip to content

Commit 56f0ccb

Browse files
Enhances the exception message displayed when a parameter mismatch occurs in Before/After events and expressions
1 parent 0d2cad2 commit 56f0ccb

File tree

1 file changed

+107
-2
lines changed

1 file changed

+107
-2
lines changed

dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)