Jak mogę odkryć „ścieżkę” osadzonego zasobu?

110

Przechowuję plik PNG jako zasób osadzony w zestawie. Z tego samego zestawu mam taki kod:

Bitmap image = new Bitmap(typeof(MyClass), "Resources.file.png");

Plik o nazwie „file.png” jest przechowywany w folderze „Resources” (w programie Visual Studio) i jest oznaczony jako zasób osadzony.

Kod kończy się niepowodzeniem z wyjątkiem:

Nie można znaleźć zasobu MyNamespace.Resources.file.png w klasie MyNamespace.MyClass

Mam identyczny kod (w innym zestawie, ładowanie innego zasobu), który działa. Więc wiem, że technika jest dobra. Mój problem polega na tym, że spędzam dużo czasu próbując dowiedzieć się, jaka jest właściwa ścieżka. Gdybym mógł po prostu wysłać zapytanie (np. W debugerze) do zestawu, aby znaleźć właściwą ścieżkę, zaoszczędziłoby mi to mnóstwa bólu głowy.

Obrabować
źródło

Odpowiedzi:

198

W ten sposób otrzymasz tablicę ciągów wszystkich zasobów:

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
Jan
źródło
3
Hej, jak mogę uzyskać ścieżkę do folderu zasobów, aby przypisać go jako katalog główny dla mojego wbudowanego serwera http?
lazzy_ms
45

Za każdym razem zapominam, jak to zrobić, więc po prostu zawijam dwa jednowierszowe, których potrzebuję, w małej klasie:

public class Utility
{
    /// <summary>
    /// Takes the full name of a resource and loads it in to a stream.
    /// </summary>
    /// <param name="resourceName">Assuming an embedded resource is a file
    /// called info.png and is located in a folder called Resources, it
    /// will be compiled in to the assembly with this fully qualified
    /// name: Full.Assembly.Name.Resources.info.png. That is the string
    /// that you should pass to this method.</param>
    /// <returns></returns>
    public static Stream GetEmbeddedResourceStream(string resourceName)
    {
        return Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
    }

    /// <summary>
    /// Get the list of all emdedded resources in the assembly.
    /// </summary>
    /// <returns>An array of fully qualified resource names</returns>
    public static string[] GetEmbeddedResourceNames()
    {
        return Assembly.GetExecutingAssembly().GetManifestResourceNames();
    }
}
Dylan
źródło
19

Domyślam się, że twoja klasa znajduje się w innej przestrzeni nazw. Kanonicznym sposobem rozwiązania tego problemu byłoby użycie klasy zasobów i zasobu o jednoznacznie określonym typie:

ProjectNamespace.Properties.Resources.file

Użyj menedżera zasobów IDE, aby dodać zasoby.

Konrad Rudolph
źródło
Masz rację, moja klasa znajduje się w innej przestrzeni nazw. Wygląda na to, że folder Resources znajduje się w przestrzeni nazw określonej jako domyślna przestrzeń nazw w konfiguracji projektu, która z różnych powodów nie jest przestrzenią nazw, do której należy ta klasa. Podejrzewam, że masz rację również co do stosowania zupełnie innego podejścia, ale ponieważ muszę być spójny ze starszym kodem, jest to poza moją kontrolą.
Rob
7
To pobiera zasób, a nie ścieżkę do pliku.
Uchiha Itachi
3
@UchihaItachi Dlatego właśnie udzieliłem tej odpowiedzi wyraźnie jako innego (i prawdopodobnie kanonicznego) sposobu rozwiązania podstawowego problemu, zamiast odpowiadać na pytanie dosłownie (które w każdym razie ma już odpowiedź).
Konrad Rudolph
1
@UchihaItachi Pytanie mówi również o problemie, z którym boryka się pytająca osoba, jakie jest jej podejście i jak do tej pory próbował. Chociaż Rudolph nie odpowiada bezpośrednio na pytanie, przedstawia inne podejście do rozwiązania problemu. W większości przypadków takie podejście jest wygodniejsze, bezpieczniejsze i powszechniejsze. Ta odpowiedź jest pomocna. Po prostu nie rozumiem, dlaczego musisz próbować zamknąć odpowiedzi ludzi. Przyciski Głosuj za / Głosuj na dół są nie bez powodu.
Nin
5

Używam następującej metody, aby pobrać osadzone zasoby:

    protected static Stream GetResourceStream(string resourcePath)
    {
        Assembly assembly = Assembly.GetExecutingAssembly();
        List<string> resourceNames = new List<string>(assembly.GetManifestResourceNames());

        resourcePath = resourcePath.Replace(@"/", ".");
        resourcePath = resourceNames.FirstOrDefault(r => r.Contains(resourcePath));

        if (resourcePath == null)
            throw new FileNotFoundException("Resource not found");

        return assembly.GetManifestResourceStream(resourcePath);
    }

Następnie nazywam to ścieżką w projekcie:

GetResourceStream(@"DirectoryPathInLibrary/Filename")
masterwok
źródło
3

Nazwa zasobu to przestrzeń nazw plus przestrzeń nazw „pseudo” ścieżki do pliku. Przestrzeń nazw „pseudo” jest tworzona przez strukturę podfolderów za pomocą \ (ukośników odwrotnych) zamiast. (kropki).

public static Stream GetResourceFileStream(String nameSpace, String filePath)
{
    String pseduoName = filePath.Replace('\\', '.');
    Assembly assembly = Assembly.GetExecutingAssembly();
    return assembly.GetManifestResourceStream(nameSpace + "." + pseduoName);
}

Następujące wezwanie:

GetResourceFileStream("my.namespace", "resources\\xml\\my.xml")

zwróci strumień my.xml znajdujący się w strukturze folderów resources \ xml w przestrzeni nazw: my.namespace.

user3356450
źródło
6
Również myślniki („-”) w folderach są zastępowane podkreśleniami („_”). Mogą być również inne symbole. Chciałbym zobaczyć, jak robi to kompilator, abyśmy mogli użyć tej samej metody.
Bojko Karadzhow