From 56f0ccbe0622643a23eba1ecdd661b4e196d39e2 Mon Sep 17 00:00:00 2001 From: cmurialdo Date: Thu, 6 Jul 2023 10:14:41 -0300 Subject: [PATCH 1/2] Enhances the exception message displayed when a parameter mismatch occurs in Before/After events and expressions --- .../GxClasses/Helpers/GXMetadata.cs | 109 +++++++++++++++++- 1 file changed, 107 insertions(+), 2 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs index ae6a24b09..1be077f26 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs @@ -15,6 +15,7 @@ namespace GeneXus.Metadata #endif using GeneXus.Application; using System.Collections.Concurrent; + using System.Text; public class ClassLoader { @@ -267,7 +268,10 @@ static public void ExecuteVoidRef(object o, string mthd, Object[] args) pm[0] = ((pi.Attributes & ParameterAttributes.In) != ParameterAttributes.None); pm[1] = ((pi.Attributes & ParameterAttributes.Out) != ParameterAttributes.None); pm[2] = pi.ParameterType.IsByRef; - pms[i] = pm; + if (i < pms.Length) + { + pms[i] = pm; + } } try { @@ -275,7 +279,7 @@ static public void ExecuteVoidRef(object o, string mthd, Object[] args) }catch(MissingMethodException) { - throw new GxClassLoaderException("Method " + mi.DeclaringType.FullName + "." + mi.Name + " for " + args.Length + " parameters ("+ String.Join(",", args) + ") not found"); + throw new GxClassLoaderException(BuildParameterMismatchErrorMessage(mi.DeclaringType.FullName, pis, args)); } } else @@ -292,6 +296,107 @@ static public void ExecuteVoidRef(object o, string mthd, Object[] args) throw GxClassLoaderException.ProcessException(e); } } + static string BuildParameterMismatchErrorMessage(string objectName, ParameterInfo[] methodParameters, object[] runtimeMethodParameters) + { + string parmInfo = GetParameterTypesString(methodParameters); + string runtimeParms = GetParameterValuesString(runtimeMethodParameters); + StringBuilder errorMessage = new StringBuilder(); + if (methodParameters.Length == 0) + { + errorMessage.Append($"The object {objectName} does not have any parameters, thus it does not match the "); + } + else if (methodParameters.Length == 1) + { + errorMessage.Append($"The parm rule of {objectName} with parameter: {parmInfo} does not match the "); + } + else + { + errorMessage.Append($"The parm rule of {objectName} with parameters: {parmInfo} does not match the "); + } + + if (runtimeMethodParameters.Length == 0) + { + errorMessage.Append($"absence of values provided at runtime. "); + } + else if (runtimeMethodParameters.Length == 1) + { + errorMessage.Append($"value provided in runtime: {runtimeParms}. "); + } + else + { + errorMessage.Append($"values provided in runtime: {runtimeParms}. "); + } + errorMessage.Append($"Please check the parm rule of the {objectName}."); + + return errorMessage.ToString(); + } + + static string GetParameterValuesString(object[] runtimeMethodParameters) + { + StringBuilder sb = new StringBuilder(); + sb.Append('('); + + for (int i = 0; i < runtimeMethodParameters.Length; i++) + { + object parmValue = runtimeMethodParameters[i]; + string parmStringValue = (parmValue is string) ? $"\"{parmValue}\"" : parmValue.ToString(); + sb.Append(parmStringValue); + if (i < runtimeMethodParameters.Length - 1) + { + sb.Append(", "); + } + } + sb.Append(')'); + return sb.ToString(); + } + + static string GetParameterTypesString(ParameterInfo[] parameters) + { + StringBuilder sb = new StringBuilder(); + sb.Append('('); + + for (int i = 0; i < parameters.Length; i++) + { + string parmTypeName = ParameterTypeName(parameters[i].ParameterType); + sb.Append(parmTypeName); + if (i < parameters.Length - 1) + { + sb.Append(", "); + } + } + sb.Append(')'); + return sb.ToString(); + } + + static string ParameterTypeName(Type parameterType) + { + Type innerType = (parameterType.IsByRef && parameterType.GetElementType()!=null) ? parameterType.GetElementType() : parameterType; + if (IsNumericType(innerType)) + return "Numeric"; + return innerType.Name; + } + + static bool IsNumericType(Type type) + { + if (type == typeof(byte) || + type == typeof(sbyte) || + type == typeof(short) || + type == typeof(ushort) || + type == typeof(int) || + type == typeof(uint) || + type == typeof(long) || + type == typeof(ulong) || + type == typeof(float) || + type == typeof(double) || + type == typeof(decimal)) + { + return true; + } + else + { + return false; + } + } static public void ExecuteRef(object o, string mthd, Object[] args) { GXLogging.Debug(log, "ExecuteRef '" + "class '" + o + "' mthd '" + mthd + "'"); From 6f619e8c4b9a5bc6f951e6daef60b0cb6345a0c1 Mon Sep 17 00:00:00 2001 From: cmurialdo Date: Thu, 6 Jul 2023 14:49:51 -0300 Subject: [PATCH 2/2] Specify event name on Parameter Mismatch Error Message --- .../GxClasses/Core/GXApplication.cs | 12 ++++---- .../GxClasses/Helpers/GXMetadata.cs | 30 +++++++++++-------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs index ff39ab1d5..27eed1ebf 100644 --- a/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs +++ b/dotnet/src/dotnetframework/GxClasses/Core/GXApplication.cs @@ -3173,7 +3173,7 @@ public void ExecuteBeforeCommit(string callerName) { inBeforeCommit = true; if (beforeCommitObj != null) - ClassLoader.ExecuteVoidRef(beforeCommitObj, "execute", new Object[] { callerName }); + ClassLoader.ExecuteVoidRef(beforeCommitObj, "execute", new Object[] { callerName }, "Before Commit"); inBeforeCommit = false; } } @@ -3184,7 +3184,7 @@ public void ExecuteAfterCommit(string callerName) { inAfterCommit = true; if (afterCommitObj != null) - ClassLoader.ExecuteVoidRef(afterCommitObj, "execute", new Object[] { callerName }); + ClassLoader.ExecuteVoidRef(afterCommitObj, "execute", new Object[] { callerName },"After Commit"); inAfterCommit = false; } } @@ -3195,7 +3195,7 @@ public void ExecuteBeforeRollback(string callerName) { inBeforeRollback = true; if (beforeRollbackObj != null) - ClassLoader.ExecuteVoidRef(beforeRollbackObj, "execute", new Object[] { callerName }); + ClassLoader.ExecuteVoidRef(beforeRollbackObj, "execute", new Object[] { callerName }, "Before Rollback"); inBeforeRollback = false; } } @@ -3206,7 +3206,7 @@ public void ExecuteAfterRollback(string callerName) { inAfterRollback = true; if (afterRollbackObj != null) - ClassLoader.ExecuteVoidRef(afterRollbackObj, "execute", new Object[] { callerName }); + ClassLoader.ExecuteVoidRef(afterRollbackObj, "execute", new Object[] { callerName }, "After Rollback"); inAfterRollback = false; } } @@ -3216,7 +3216,7 @@ public bool ExecuteBeforeConnect(IGxDataStore datastore) if (beforeConnectObj != null) { GXLogging.Debug(log, "ExecuteBeforeConnect"); - ClassLoader.ExecuteVoidRef(beforeConnectObj, "execute", new Object[] { datastore }); + ClassLoader.ExecuteVoidRef(beforeConnectObj, "execute", new Object[] { datastore }, "Before Connect"); return true; } else @@ -3230,7 +3230,7 @@ public bool ExecuteAfterConnect(String datastoreName) if (afterConnectObj != null) { GXLogging.Debug(log, "ExecuteAfterConnect"); - ClassLoader.ExecuteVoidRef(afterConnectObj, "execute", new Object[] { datastoreName }); + ClassLoader.ExecuteVoidRef(afterConnectObj, "execute", new Object[] { datastoreName }, "After Connect"); return true; } else diff --git a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs index 1be077f26..20a5c51bc 100644 --- a/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs +++ b/dotnet/src/dotnetframework/GxClasses/Helpers/GXMetadata.cs @@ -232,8 +232,11 @@ internal static string ConstructorArgsString(Object[] constructorArgs) } return argsConstr; } - static public void ExecuteVoidRef(object o, string mthd, Object[] args) + { + ExecuteVoidRef(o, mthd, args, null); + } + internal static void ExecuteVoidRef(object o, string mthd, Object[] args, string propertyName) { try { @@ -279,7 +282,7 @@ static public void ExecuteVoidRef(object o, string mthd, Object[] args) }catch(MissingMethodException) { - throw new GxClassLoaderException(BuildParameterMismatchErrorMessage(mi.DeclaringType.FullName, pis, args)); + throw new GxClassLoaderException(BuildParameterMismatchErrorMessage(mi.DeclaringType.FullName, pis, args, propertyName)); } } else @@ -296,35 +299,38 @@ static public void ExecuteVoidRef(object o, string mthd, Object[] args) throw GxClassLoaderException.ProcessException(e); } } - static string BuildParameterMismatchErrorMessage(string objectName, ParameterInfo[] methodParameters, object[] runtimeMethodParameters) + static string BuildParameterMismatchErrorMessage(string objectName, ParameterInfo[] methodParameters, object[] runtimeMethodParameters, string propertyName) { string parmInfo = GetParameterTypesString(methodParameters); string runtimeParms = GetParameterValuesString(runtimeMethodParameters); StringBuilder errorMessage = new StringBuilder(); - if (methodParameters.Length == 0) + + errorMessage.Append($"Program {objectName} "); + if (!string.IsNullOrEmpty(propertyName)) { - errorMessage.Append($"The object {objectName} does not have any parameters, thus it does not match the "); + errorMessage.Append($"referenced in {propertyName} property "); } - else if (methodParameters.Length == 1) + errorMessage.Append($"does not have the expected parameter definition."); + if (methodParameters.Length == 0) { - errorMessage.Append($"The parm rule of {objectName} with parameter: {parmInfo} does not match the "); + errorMessage.Append($"It does not have any parameters."); } - else + else { - errorMessage.Append($"The parm rule of {objectName} with parameters: {parmInfo} does not match the "); + errorMessage.Append($"Program parameter definition: {parmInfo}."); } if (runtimeMethodParameters.Length == 0) { - errorMessage.Append($"absence of values provided at runtime. "); + errorMessage.Append($"No parameter values were provided at runtime. "); } else if (runtimeMethodParameters.Length == 1) { - errorMessage.Append($"value provided in runtime: {runtimeParms}. "); + errorMessage.Append($"Parameter value provided at runtime: {runtimeParms}. "); } else { - errorMessage.Append($"values provided in runtime: {runtimeParms}. "); + errorMessage.Append($"Parameter values provided at runtime: {runtimeParms}. "); } errorMessage.Append($"Please check the parm rule of the {objectName}.");