Given a pack:// URI, what's the best way to tell whether a compiled resource (e.g. a PNG image, compiled with a Build Action of "Resource") actually exists at that URI?
After some stumbling around, I came up with this code, which works but is clumsy:
private static bool CanLoadResource(Uri uri)
{
try
{
Application.GetResourceStream(uri);
return true;
}
catch (IOException)
{
return false;
}
}
(Note that the Application.GetResources documentation is wrong -- it throws an exception if the resource isn't found, rather than returning null like the docs incorrectly state.) (The docs have been corrected, see comments below)
I don't like catching exceptions to detect an expected (non-exceptional) result. And besides, I don't actually want to load the stream, I just want to know whether it exists.
Is there a better way to do this, perhaps with lower-level resource APIs -- ideally without actually loading the stream and without catching an exception?
I've found a solution that I'm using which doesn't work directly with a pack Uri but instead looks up a resource by it's resource path. That being said, this example could be modified pretty easily to support a pack URI instead by just tacking on the resource path to the end of a uri which uses the Assembly to formulate the base part of the 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();
}
}