when<T> method

  1. @override
Future<T> when<T>(
  1. AsyncMethodInvocator<T> function,
  2. Object target,
  3. String methodName, [
  4. ExecutableArgument? arguments,
  5. Class? targetClass,
])
override

Executes a function with interception support and conditional routing.

This method acts as the central dispatcher that controls whether and how interceptors are applied to a particular function call. It can manage ordered chains, invoke nested interceptors, or delegate directly to the underlying function when no applicable interceptors exist.

Parameters

  • function: The function to execute, typically the original method or a wrapped invocator.
  • target: The target object or class for which the function is being invoked.
  • arguments: (Optional) The method arguments to be passed during invocation.
  • methodName: (Optional) The name of the method being invoked, for matching or diagnostics.
  • targetClass: (Optional) The target class where the method can be found on.

@return The result of the function execution, potentially modified by interceptors.

Implementation

@override
Future<T> when<T>(AsyncMethodInvocator<T> function, Object target, String methodName, [ExecutableArgument? arguments, Class? targetClass]) async {
  final customDispatcher = getMethodInterceptorDispatcher();

  if (customDispatcher != null) {
    return customDispatcher.when(function, target, methodName, arguments);
  }

  targetClass ??= target.getClass();

  if (ClassUtils.isProxyClass(targetClass)) {
    targetClass = ClassUtils.getProxiedClass(target.getClass(), target);
  }

  final method = targetClass.getMethod(methodName);

  // Before proceeding, we need to make sure that the method name actually lives in the target class.
  if (method != null) {
    MethodInvocation<T> invocation = SimpleMethodInvocation(target, targetClass, method, arguments, function);
    final result = await intercept<T>(invocation);

    if (result != null) {
      return result;
    }

    return invocation.proceed();
  } else if (method == null) {
    throw IllegalArgumentException('''
JetLeaf could not locate the method `$methodName` in class `${targetClass.getQualifiedName()}`.

Possible causes:
β€’ The method `$methodName` is not declared in `${targetClass.getName()}` or its superclasses.
β€’ The method belongs to a mixin or interface and is not directly implemented in the target class.

πŸ” Diagnostic details:
- Target class: ${targetClass.getQualifiedName()}
- Requested method: $methodName
- Available methods: ${targetClass.getMethods().map((m) => m.getName()).join(', ')}

πŸ’‘ Recommended fixes:
β†’ Verify that `$methodName` exists and is declared in `${targetClass.getName()}`.
β†’ If using mixins or abstract classes, ensure the concrete implementation defines `$methodName`.
β†’ If reflection metadata is out of date, rebuild your project or regenerate proxy files.

Example:
```dart
final result = await when(
() => createUser(user),
service,
'createUser',
ExecutableArgument(positionalArgs: [user])
);
```
''');
  }

  return function();
}