Определить, существует ли ресурс WPF на основе URI

учитывая pack: / / URI, каков наилучший способ узнать, существует ли скомпилированный ресурс (например, PNG-изображение, скомпилированное с действием сборки "Resource") В этом URI?

после некоторого спотыкания я придумал этот код, который работает, но неуклюжий:

private static bool CanLoadResource(Uri uri)
{
    try
    {
        Application.GetResourceStream(uri);
        return true;
    }
    catch (IOException)
    {
        return false;
    }
}

(заметьте, что тег приложение.GetResources документация не так -- он выдает исключение, если ресурс не найден, а не возвращает null как неверное состояние документов.) (документы были исправлены, см. комментарий ниже)

мне не нравится ловить исключения для обнаружения ожидаемого (не исключительного) результата. И кроме того, я на самом деле не хочу загружать поток, я просто хочу знать, существует ли он.

есть ли лучший способ сделать это, возможно, с API ресурсов более низкого уровня-в идеале без фактической загрузки потока и без улавливания исключения?

1 ответов


Я нашел решение, которое я использую, которое не работает непосредственно с Uri пакета, но вместо этого ищет ресурс по пути к ресурсу. Тем не менее, этот пример может быть изменен довольно легко для поддержки URI пакета вместо этого, просто лавируя по пути к ресурсу до конца uri, который использует сборку для формулирования базовой части URI.

public static bool ResourceExists(string resourcePath)
{
    var assembly = Assembly.GetExecutingAssembly();

    return ResourceExists(assembly, resourcePath);
}

public static bool ResourceExists(Assembly assembly, string resourcePath)
{
    return GetResourcePaths(assembly)
        .Contains(resourcePath.ToLowerInvariant());
}

public static IEnumerable<object> GetResourcePaths(Assembly assembly)
{
    var culture = System.Threading.Thread.CurrentThread.CurrentCulture;
    var resourceName = assembly.GetName().Name + ".g";
    var resourceManager = new ResourceManager(resourceName, assembly);

    try
    {
        var resourceSet = resourceManager.GetResourceSet(culture, true, true);

        foreach(System.Collections.DictionaryEntry resource in resourceSet)
        {
            yield return resource.Key;
        }
    }
    finally
    {
        resourceManager.ReleaseAllResources();
    }
}