2010-01-06 12 views
11

Dado un URI de paquete: //, ¿cuál es la mejor manera de saber si un recurso compilado (por ejemplo, una imagen PNG, compilado con una Acción de compilación de "Recurso") existe realmente en ese URI?Detectar si existe recurso WPF, basado en URI

Después de algún dando tumbos, me ocurrió con este código, que funciona, pero es torpe:

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

(Tenga en cuenta que la documentación Application.GetResourcesis wrong - lanza una excepción si no se encuentra el recurso , en lugar de volver nula al igual que los documentos indican incorrectamente.)(los documentos han sido corregidos, ver comentarios más abajo)

no me gusta la captura de excepciones para detectar un no excepcional resultado esperado(). Y además, en realidad no quiero cargar la transmisión, solo quiero saber si existe.

¿Existe alguna forma mejor de hacerlo, quizás con API de recursos de nivel más bajo, idealmente sin cargar realmente la transmisión y sin capturar una excepción?

+0

Se actualizó el documento, dice que arroja una excepción cuando no se encuentra el recurso. – Shimmy

+1

@Shimmy, gracias por la actualización: he editado para incluir esa información. –

+0

@John White: Por cierto, creo que deberías marcar [la publicación de jpierson] (http://stackoverflow.com/questions/2013481/detect-whether-wpf-resource-exists-based-on-uri/2549641#2549641) como responder. – Shimmy

Respuesta

10

He encontrado una solución que estoy usando que no funciona directamente con un paquete Uri pero en su lugar busca un recurso por su ruta de recursos. Dicho esto, este ejemplo podría modificarse bastante fácilmente para admitir un URI de paquete en su lugar simplemente haciendo tachuelas en la ruta de acceso de recursos al final de un uri que usa el ensamblado para formular la parte base del 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

Parece que las rutas devueltas de 'GetResourcePaths' están en minúsculas, así que asegúrese de usar' .Contains (resourcePath.ToLower()); 'en el método' ResourceExists'. –

+2

Haz que '.ToLowerInvariant()' solo para estar seguro. – RandomEngy

Cuestiones relacionadas