Определить, существует ли ресурс WPF на основе URI - PullRequest
13 голосов
/ 06 января 2010

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

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

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

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

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

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

1 Ответ

10 голосов
/ 31 марта 2010

Я нашел решение, которое я использую, которое не работает напрямую с пакетом 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();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...