From 77e9bcb4eb90e353c34ece6ea26aecc55073eb90 Mon Sep 17 00:00:00 2001 From: Sergiy Kurinny <59140005+generalloki@users.noreply.github.com> Date: Tue, 6 May 2025 11:51:13 +0300 Subject: [PATCH 1/2] MethodBinderEvents.CoerceBind --- src/runtime/MethodBinder.cs | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/src/runtime/MethodBinder.cs b/src/runtime/MethodBinder.cs index af75a34b4..897892b8f 100644 --- a/src/runtime/MethodBinder.cs +++ b/src/runtime/MethodBinder.cs @@ -9,6 +9,12 @@ namespace Python.Runtime { using MaybeMethodBase = MaybeMethodBase; + + public delegate void MethodBinderCoerceBindDelegate( + Dictionary arguments, + MethodBase[] methods, + ref MethodBase? foundBinding); + /// /// A MethodBinder encapsulates information about a (possibly overloaded) /// managed method, and is responsible for selecting the right method given @@ -516,7 +522,7 @@ public MismatchedMethod(Exception exception, MethodBase mb) } } - return new Binding(mi, target, margs, outs); + return CoerceResult(new Binding(mi, target, margs, outs)); } else if (matchGenerics && isGeneric) { @@ -528,7 +534,7 @@ public MismatchedMethod(Exception exception, MethodBase mb) MethodInfo[] overloads = MatchParameters(methods, types); if (overloads.Length != 0) { - return Bind(inst, args, kwargDict, overloads, matchGenerics: false); + return CoerceResult(Bind(inst, args, kwargDict, overloads, matchGenerics: false)); } } if (mismatchedMethods.Count > 0) @@ -537,6 +543,19 @@ public MismatchedMethod(Exception exception, MethodBase mb) Exceptions.SetError(aggregateException); } return null; + + Binding? CoerceResult(Binding? binding) + { + if (binding is not null) + { + var foundMethod = binding.info; + MethodBinderEvents.CoerceBind?.Invoke(kwargDict, methods, ref foundMethod); + if (foundMethod is null) + return null; + } + + return binding; + } } static AggregateException GetAggregateException(IEnumerable mismatchedMethods) @@ -1068,4 +1087,9 @@ static internal class ParameterInfoExtensions } } } + + public static class MethodBinderEvents + { + public static MethodBinderCoerceBindDelegate? CoerceBind; + } } From aa8e833c322bb352ac6ce090193b7a370e41eef6 Mon Sep 17 00:00:00 2001 From: Sergiy Kurinny <59140005+generalloki@users.noreply.github.com> Date: Tue, 6 May 2025 15:20:12 +0300 Subject: [PATCH 2/2] Update MethodBinder.cs --- src/runtime/MethodBinder.cs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/runtime/MethodBinder.cs b/src/runtime/MethodBinder.cs index 897892b8f..1ac5f5c05 100644 --- a/src/runtime/MethodBinder.cs +++ b/src/runtime/MethodBinder.cs @@ -10,6 +10,16 @@ namespace Python.Runtime { using MaybeMethodBase = MaybeMethodBase; + /// + /// Delegate for custom coercion logic during Python method binding. + /// + /// A dictionary containing the Python arguments passed to the method. + /// An array of method overloads being considered for binding. + /// + /// A reference to the method that was successfully bound. This can be modified by the delegate + /// to override the default binding logic. The delegate can set this to null to disable the method call + /// and report an error. + /// public delegate void MethodBinderCoerceBindDelegate( Dictionary arguments, MethodBase[] methods, @@ -1088,8 +1098,14 @@ static internal class ParameterInfoExtensions } } + /// + /// Provides events related to method binding in the MethodBinder class. + /// public static class MethodBinderEvents { + /// + /// Event triggered to allow custom coercion logic during method binding. + /// public static MethodBinderCoerceBindDelegate? CoerceBind; } }