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.

Odpowiedzi:


198

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

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();

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();
    }
}

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.


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")

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.


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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.