2008-08-26 7 views
81

Je stocke un fichier PNG en tant que ressource incorporée dans un assembly. À partir du même ensemble que j'ai un code comme ceci:Comment puis-je découvrir le "chemin" d'une ressource incorporée?

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

Le fichier, nommé « file.png » est stocké dans le dossier « Ressources » (au sein de Visual Studio), et est marqué comme une ressource incorporée.

Le code échoue avec une exception en disant:

ressources MyNamespace.Resources.file.png ne peut être trouvé dans la classe MyNamespace.MyClass

J'ai code identique (dans un autre assemblage, chargement d'une ressource différente) qui fonctionne. Donc je sais que la technique est saine. Mon problème est que je finis par passer beaucoup de temps à essayer de comprendre quel est le bon chemin. Si je pouvais simplement interroger (par exemple dans le débogueur) l'assemblage pour trouver le chemin correct, cela me sauverait une charge de maux de tête.

Répondre

156

Cela vous obtiendrez un tableau de chaîne de toutes les ressources:

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

Assez utile! Merci! –

15

Je suppose que votre classe est dans un espace de noms différent. La manière canonique pour résoudre ce serait d'utiliser la classe des ressources et une ressource fortement typé:

ProjectNamespace.Properties.Resources.file 

Utilisez le gestionnaire de ressources de l'EDI pour ajouter des ressources.

+0

Vous avez raison, ma classe est dans un espace de noms différent. Il semble que le dossier Resources se trouve sous l'espace de noms spécifié en tant qu'espace de noms par défaut dans la configuration du projet, ce qui n'est pas, pour diverses raisons, l'espace de noms dont fait partie cette classe. Je suppose que vous avez raison d'utiliser une approche différente, mais comme je dois être cohérent avec le code existant, cela ne dépend pas de moi. – Rob

+0

Cela saisit la ressource - pas son chemin de fichier. –

+0

@UchihaItachi C'est pourquoi j'ai proposé cette réponse explicitement comme une autre façon (et sans doute canonique) de résoudre le * problème sous-jacent * plutôt que de répondre à la question mot pour mot (qui a déjà une réponse). –

41

je me trouve oublier comment faire cela à chaque fois, si bien que je viens envelopper les deux one-liners que j'ai besoin dans un petit classe:

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

le nom de la ressource est l'espace de nom plus l'espace de nom « pseudo » du chemin du fichier. L'espace de noms "pseudo" est créé par la structure du sous-dossier en utilisant \ (backslashes) au lieu de. (points).

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

L'appel suivant:

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

retournera le flux de my.xml situé dans les ressources de structure du dossier \ xml dans l'espace de nom: my.namespace.

+4

Les tirets ('-') dans les dossiers sont également remplacés par des traits de soulignement ('_'). Il pourrait y avoir d'autres symboles aussi. Je voudrais voir comment le compilateur le fait pour que nous puissions utiliser la même méthode. –

5

J'utilise la méthode suivante pour récupérer des ressources incorporées:

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

J'appelle alors cela avec le chemin du projet:

GetResourceStream(@"DirectoryPathInLibrary/Filename") 
Questions connexes