protected function findFirstEligibleTypeConverterInObjectHierarchy($source, $sourceType, $targetType)
    {
        $targetClass = TypeHandling::truncateElementType($targetType);
        if (!class_exists($targetClass) && !interface_exists($targetClass)) {
            throw new Exception\InvalidTargetException(sprintf('Could not find a suitable type converter for "%s" because the class / interface "%s" does not exist.', $targetType, $targetClass), 1297948764);
        }

        if (!isset($this->typeConverters[$sourceType])) {
            return null;
        }

        $convertersForSource = $this->typeConverters[$sourceType];
        if (isset($convertersForSource[$targetClass])) {
            $converter = $this->findEligibleConverterWithHighestPriority($convertersForSource[$targetClass], $source, $targetType);
            if ($converter !== null) {
                return $converter;
            }
        }

        foreach (class_parents($targetClass) as $parentClass) {
            if (!isset($convertersForSource[$parentClass])) {
                continue;
            }

            $converter = $this->findEligibleConverterWithHighestPriority($convertersForSource[$parentClass], $source, $targetType);
            if ($converter !== null) {
                return $converter;
            }
        }

        $converters = $this->getConvertersForInterfaces($convertersForSource, class_implements($targetClass));
        $converter = $this->findEligibleConverterWithHighestPriority($converters, $source, $targetType);

        if ($converter !== null) {
            return $converter;
        }
        if (isset($convertersForSource['object'])) {
            return $this->findEligibleConverterWithHighestPriority($convertersForSource['object'], $source, $targetType);
        } else {
            return null;
        }
    }