diff --git a/src/runtime/MethodBinder.cs b/src/runtime/MethodBinder.cs index af75a34b4..1ac5f5c05 100644 --- a/src/runtime/MethodBinder.cs +++ b/src/runtime/MethodBinder.cs @@ -9,6 +9,22 @@ 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, + ref MethodBase? foundBinding); + /// /// A MethodBinder encapsulates information about a (possibly overloaded) /// managed method, and is responsible for selecting the right method given @@ -516,7 +532,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 +544,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 +553,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 +1097,15 @@ 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; + } }