Wie kann ich den „Pfad“ einer eingebetteten Ressource ermitteln?

109

Ich speichere ein PNG als eingebettete Ressource in einer Assembly. Aus derselben Assembly heraus habe ich folgenden Code:

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

Die Datei mit dem Namen "file.png" wird im Ordner "Resources" (in Visual Studio) gespeichert und als eingebettete Ressource markiert.

Der Code schlägt mit einer Ausnahme fehl, die besagt:

Die Ressource MyNamespace.Resources.file.png kann nicht in der Klasse MyNamespace.MyClass gefunden werden

Ich habe identischen Code (in einer anderen Assembly, Laden einer anderen Ressource), der funktioniert. Ich weiß also, dass die Technik solide ist. Mein Problem ist, dass ich am Ende viel Zeit damit verbringe, herauszufinden, was der richtige Weg ist. Wenn ich einfach (z. B. im Debugger) die Assembly abfragen könnte, um den richtigen Pfad zu finden, würde mir das eine Menge Kopfschmerzen ersparen.

rauben
quelle

Antworten:

197

Dadurch erhalten Sie ein String-Array aller Ressourcen:

System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames();
John
quelle
3
Hey, wie kann ich den Pfad des Ressourcenordners dazu bringen, ihn als Root-Verzeichnis für meinen eingebetteten http-Server zuzuweisen?
Lazy_ms
45

Ich vergesse jedes Mal, wie man das macht, also wickle ich einfach die zwei Einzeiler, die ich brauche, in eine kleine Klasse:

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
quelle
19

Ich vermute, dass sich Ihre Klasse in einem anderen Namespace befindet. Der kanonische Weg, dies zu lösen, wäre die Verwendung der Ressourcenklasse und einer stark typisierten Ressource:

ProjectNamespace.Properties.Resources.file

Verwenden Sie den Ressourcenmanager der IDE, um Ressourcen hinzuzufügen.

Konrad Rudolph
quelle
Sie haben Recht, meine Klasse befindet sich in einem anderen Namespace. Es scheint, dass der Ordner "Ressourcen" unter dem Namespace liegt, der in der Projektkonfiguration als Standardnamespace angegeben ist. Dies ist aus verschiedenen Gründen nicht der Namespace, zu dem diese Klasse gehört. Ich vermute, Sie haben Recht, auch wenn Sie einen völlig anderen Ansatz verwenden, aber da ich mit Legacy-Code konsistent sein muss, liegt dies außerhalb meiner Kontrolle.
Rob
7
Dadurch wird die Ressource erfasst - nicht der Dateipfad.
Uchiha Itachi
3
@UchihaItachi Deshalb habe ich diese Antwort explizit als eine andere (und wohl kanonische) Möglichkeit angeboten, das zugrunde liegende Problem zu lösen, anstatt die Frage wörtlich zu beantworten (die jedenfalls bereits eine Antwort hat).
Konrad Rudolph
1
@UchihaItachi Die Frage zeigt auch das Problem, mit dem die fragende Person konfrontiert ist, wie sie vorgeht und wie sie es bisher versucht hat. Obwohl Rudolph die Frage nicht direkt beantwortet, spricht er einen anderen Ansatz zur Lösung des Problems an. In den meisten Fällen ist dieser Ansatz bequemer, sicherer und üblicher. Diese Antwort ist hilfreich. Ich verstehe nur nicht, warum Sie versuchen müssen, die Antworten der Leute abzuschalten. Abstimmungs- / Abstimmungsschaltflächen gibt es aus einem bestimmten Grund.
Nin
5

Ich verwende die folgende Methode, um eingebettete Ressourcen zu erfassen:

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

Ich nenne das dann mit dem Pfad im Projekt:

GetResourceStream(@"DirectoryPathInLibrary/Filename")
Masterwok
quelle
3

Der Name der Ressource ist der Namensraum plus der "Pseudo" -Namensraum des Pfads zur Datei. Der "Pseudo" -Namensraum wird von der Unterordnerstruktur mit \ (Backslashes) anstelle von erstellt. (Punkte).

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

Der folgende Aufruf:

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

gibt den Stream von my.xml zurück, der sich in der Ordnerstruktur resources \ xml im Namensraum befindet: my.namespace.

user3356450
quelle
6
Auch Bindestriche ('-') in den Ordnern werden durch Unterstriche ('_') ersetzt. Möglicherweise gibt es auch andere Symbole. Ich würde gerne sehen, wie der Compiler das macht, damit wir dieselbe Methode verwenden können.
Boyko Karadzhov