2010-01-06 6 views
11

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

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

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

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

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

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

+0

Они обновили документ, там говорится, что он выдает исключение, если ресурс не найден. – Shimmy

+1

@Shimmy, спасибо за обновление - я отредактировал эту информацию. –

+0

@John White: Кстати, я думаю, вы должны отметить [jpierson's post] (http://stackoverflow.com/questions/2013481/detect-whether-wpf-resource-exists-based-on-uri/2549641#2549641) как ответ. – Shimmy

ответ

10

Я нашел решение, которое я использую, которое не работает непосредственно с пакетом Uri, но вместо этого ищет ресурс по пути к ресурсам. При этом этот пример можно было бы довольно легко модифицировать, чтобы поддерживать URI пакета вместо этого, просто привязывая путь ресурса к концу uri, который использует Assembly для формулировки базовой части 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(); 
    } 
} 
+5

Похоже, что возвращаемые пути из 'GetResourcePaths' находятся ниже, поэтому обязательно используйте' .Contains (resourcePath.ToLower()); 'в методе' ResourceExists'. –

+2

Сделайте это .ToLowerInvariant() 'просто для того, чтобы быть в безопасности. – RandomEngy