private function makeFactory($nid, array $rule) {
        $className = empty($rule['class']) ? $nid : $rule['class'];

        if (!empty($rule['factory'])) {
            // The instance is created with a user-supplied factory function.
            $callback = $rule['factory'];
            $function = $this->reflectCallback($callback);

            if ($function->getNumberOfParameters() > 0) {
                $callbackArgs = $this->makeDefaultArgs($function, (array)$rule['constructorArgs']);
                $factory = function ($args) use ($callback, $callbackArgs) {
                    return call_user_func_array($callback, $this->resolveArgs($callbackArgs, $args));
                };
            } else {
                $factory = $callback;
            }

            // If a class is specified then still reflect on it so that calls can be made against it.
            if (class_exists($className)) {
                $class = new \ReflectionClass($className);
            }
        } else {
            // The instance is created by newing up a class.
            if (!class_exists($className)) {
                throw new NotFoundException("Class $className does not exist.", 404);
            }
            $class = new \ReflectionClass($className);
            $constructor = $class->getConstructor();

            if ($constructor && $constructor->getNumberOfParameters() > 0) {
                $constructorArgs = $this->makeDefaultArgs($constructor, (array)$rule['constructorArgs']);

                $factory = function ($args) use ($className, $constructorArgs) {
                    return new $className(...array_values($this->resolveArgs($constructorArgs, $args)));
                };
            } else {
                $factory = function () use ($className) {
                    return new $className;
                };
            }
        }

        // Add calls to the factory.
        if (isset($class) && !empty($rule['calls'])) {
            $calls = [];

            // Generate the calls array.
            foreach ($rule['calls'] as $call) {
                list($methodName, $args) = $call;
                $method = $class->getMethod($methodName);
                $calls[] = [$methodName, $this->makeDefaultArgs($method, $args)];
            }

            // Wrap the factory in one that makes the calls.
            $factory = function ($args) use ($factory, $calls) {
                $instance = $factory($args);

                foreach ($calls as $call) {
                    call_user_func_array(
                        [$instance, $call[0]],
                        $this->resolveArgs($call[1], [], $instance)
                    );
                }

                return $instance;
            };
        }

        return $factory;
    }