protected function resolveArgs($className, $methodName, $errorMessageSuffix = '', $extraMappings = []) {
		$reflectionMethod = $this->getReflectionMethod($className, $methodName);

		if (is_null($reflectionMethod) && $methodName === '__construct') {
			return [];
		}

		$extraMappings = (array)$extraMappings;

		if (isset($this->rules[$className][$methodName])) {
			$extraMappings += $this->rules[$className][$methodName];
		}

		$args = [];

		try {
			foreach ($reflectionMethod->getParameters() as $param) {
				if ($extraMappings) {
					$paramName = $param->getName();

					// Add argument according to parameter name.
					if (array_key_exists($paramName, $extraMappings)) {
						$args[] = $extraMappings[$paramName];
						continue;
					}
				}

				$paramType = $param->getType();

				// Disallow primitive types.
				if ($paramType->isBuiltin()) {
					throw new NotAllowedException("Parameter type \"$paramType\" is not allowed" . $errorMessageSuffix);
				}

				$paramClassName = $param->getClass()->getName();

				// Resolve by class.
				if (array_key_exists($paramClassName, $extraMappings)) {
					if (is_string($extraMappings[$paramClassName])) {
						$args[] = $this->get($extraMappings[$paramClassName]);
					} else {
						$args[] = $extraMappings[$paramClassName];
					}
				} else {
					$args[] = $this->get($paramClassName);
				}
			}
		} catch (ReflectionException $e) {
			throw new NotFoundException("Parameter class $paramType is not found" . $errorMessageSuffix);
		}

		return $args;
	}