parameterResolver = new ParameterResolver($container, $reflectionProvider); } /** * Führt eine Methode auf einer Klasse aus und löst alle Parameter automatisch auf */ public function invoke(ClassName|string $className, string $methodName, array $overrides = []): mixed { if(is_string($className)) { $className = ClassName::create($className); } $instance = $this->container->get($className->getFullyQualified()); return $this->invokeOn($instance, $methodName, $overrides); } /** * Führt eine Methode auf einer bereits existierenden Instanz aus */ public function invokeOn(object $instance, string $methodName, array $overrides = []): mixed { $className = ClassName::fromObject($instance); $reflection = $this->reflectionProvider->getClass($className); if (! $reflection->hasMethod($methodName)) { throw new \InvalidArgumentException( "Method $methodName does not exist on class " . $instance::class ); } // Framework WrappedReflectionMethod verwenden $method = $this->reflectionProvider->getMethod($className, $methodName); $nativeMethod = $this->reflectionProvider->getNativeMethod($className, $methodName); if (! $nativeMethod->isPublic()) { throw new \InvalidArgumentException( "Method $methodName on class " . $instance::class . " is not public" ); } $parameters = $this->resolveMethodParameters($className, $methodName, $overrides); return $nativeMethod->invokeArgs($instance, $parameters); } /** * Führt eine statische Methode aus */ public function invokeStatic(string $className, string $methodName, array $overrides = []): mixed { $classNameObj = ClassName::create($className); $reflection = $this->reflectionProvider->getClass($classNameObj); if (! $reflection->hasMethod($methodName)) { throw new \InvalidArgumentException( "Method '{$methodName}' does not exist on class '{$className}'" ); } // Framework WrappedReflectionMethod verwenden $method = $this->reflectionProvider->getMethod($classNameObj, $methodName); $nativeMethod = $this->reflectionProvider->getNativeMethod($classNameObj, $methodName); if (! $nativeMethod->isStatic()) { throw new \InvalidArgumentException( "Method '{$methodName}' on class '{$className}' is not static" ); } $parameters = $this->resolveMethodParameters($classNameObj, $methodName, $overrides); return $nativeMethod->invokeArgs(null, $parameters); } /** * Erstellt eine neue Instanz mit automatischer Dependency Injection * und optionalen Parameter-Overrides für den Constructor * * @template T of object * @param class-string $className * @param array $overrides Named constructor parameters * @return T */ public function make(string $className, array $overrides = []): object { $classNameObj = ClassName::create($className); $reflection = $this->reflectionProvider->getClass($classNameObj); if (! $reflection->isInstantiable()) { throw new \InvalidArgumentException( "Class '{$className}' is not instantiable (interface, abstract class, or trait)" ); } // Check if class has constructor if (! $reflection->hasMethod('__construct')) { return $reflection->newInstance(); } // Resolve constructor parameters with overrides $parameters = $this->resolveMethodParameters($classNameObj, '__construct', $overrides); return $reflection->newInstance(...$parameters); } /** * Löst alle Parameter einer Methode auf */ private function resolveMethodParameters(ClassName $className, string $methodName, array $overrides): array { return $this->parameterResolver->resolveMethodParameters($className, $methodName, $overrides); } }