13

pack:// URIが与えられた場合、コンパイルされたリソース(たとえば、「Resource」のビルドアクションでコンパイルされたPNGイメージ)が実際にそのURIに存在するかどうかを判断する最良の方法は何ですか?

いくつかつまずいた後、私はこのコードを思いつきました。これは機能しますが、不器用です。

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

( Application.GetResourcesのドキュメントが間違っていることに注意してください。リソースが見つからない場合は、ドキュメントの状態が正しくないようにnullを返すのではなく、例外がスローされます。) (ドキュメントは修正されています。以下のコメントを参照してください)

期待される(例外ではない)結果を検出するために例外をキャッチするのは好きではありません。また、実際にストリームをロードするのではなく、ストリームが存在するかどうかを知りたいだけです。

おそらく低レベルのリソースAPIを使用して、これを行うためのより良い方法はありますか?理想的には、実際にストリームをロードせず、例外をキャッチしませんか?

4

1 に答える 1

11

私が使用しているソリューションを見つけました。これは、パック 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();
    }
}
于 2010-03-31T00:32:57.820 に答える