Parcourez toutes les ressources d'un fichier .resx


126

Existe-t-il un moyen de parcourir toutes les ressources d'un .resxfichier en C #?


2
Pouvez-vous préciser si le fichier RESX est interne à votre projet ou si vous souhaitez (ou devez) lire un fichier RESX séparé ou lire RESX à partir d'un autre assemblage?
Abel

Réponses:


243

Vous devez toujours utiliser le gestionnaire de ressources et ne pas lire directement les fichiers pour vous assurer que la globalisation est prise en compte.

using System.Collections;
using System.Globalization;
using System.Resources;

...

/* Reference to your resources class -- may be named differently in your case */
ResourceManager MyResourceClass =
    new ResourceManager(typeof(Resources));

ResourceSet resourceSet =
    MyResourceClass.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
foreach (DictionaryEntry entry in resourceSet)
{
    string resourceKey = entry.Key.ToString();
    object resource = entry.Value;
}

12
Il m'a fallu un peu de temps pour comprendre que vous avez besoin de cette ligne pour déclarer MyResourceClass. ResourceManager MyResourceClass = new ResourceManager("Resources.ResourceFileName", System.Reflection.Assembly.Load("App_GlobalResources"));
JoeFletch

6
@JoeFletch: il n'a pas besoin de cette ligne. Le code appelle directement le fichier de ressources. Exemple: j'ai un fichier nommé PageList.resx, puis j'appellerai: ResourceSet resourceSet = PageList.ResourceManager.GetResourceSet (CultureInfo.CurrentUICulture, true, true);
Gabriel

@Gabriel, merci pour la mise à jour! Je devrai revenir à mon code pour vérifier cela.
JoeFletch

3
La ligne de JoeFletch m'a vraiment aidé. J'avais un resx dans situé dans un autre projet C #, donc sa ligne m'a permis d'appeler cet assembly dll et de charger les ressources de cette façon. Aussi, quand j'ai essayé d'inclure la PageList sur mon code, il a jeté une erreur pour PageList.ResourceManager .. disant "PageList ne contient pas une définition pour ResourceManager". Et enfin, la chaîne resourceKey = entry.Key a jeté une erreur, j'ai utilisé à la place "object resourceKey = entry.Key"
sksallaj

2
Selon que vous avez réellement des cultures définies dans votre ressource, vous devrez basculer vers CultureInfo.InvariantCulture. Ici, j'utilisais des ressources dans une bibliothèque, pas une application WinForms.
Israel Lopez

26

Blogué à ce sujet sur mon blog :) La version courte est, pour trouver les noms complets des ressources (sauf si vous les connaissez déjà):

var assembly = Assembly.GetExecutingAssembly();

foreach (var resourceName in assembly.GetManifestResourceNames())
    System.Console.WriteLine(resourceName);

Pour les utiliser tous pour quelque chose:

foreach (var resourceName in assembly.GetManifestResourceNames())
{
    using(var stream = assembly.GetManifestResourceStream(resourceName))
    {
        // Do something with stream
    }
}

Pour utiliser des ressources dans d'autres assemblys que celui en cours d'exécution, vous obtiendrez simplement un objet d'assemblage différent en utilisant certaines des autres méthodes statiques de la Assemblyclasse. J'espère que ça aide :)


Pouvez-vous énumérer les ressources qui ne se trouvent pas dans un dossier appelé «Ressource»? Je voudrais énumérer toutes les images de ressources situées dans mon projet dans un dossier appelé «Images».
Simon Bosley

Sûr qu'il ne se soucie pas de son emplacement? Essaye-le?
Svish

1
J'avais des fichiers dans un dossier pour importer des fichiers sql et cela fonctionnait parfaitement. J'ai ajouté une conversion d'un flux en chaîne afin que je puisse lire le fichier et n'ai eu aucun problème.
ErocM

9

Utiliser la classe ResXResourceReader

ResXResourceReader rsxr = new ResXResourceReader("your resource file path");

// Iterate through the resources and display the contents to the console.
foreach (DictionaryEntry d in rsxr)
{
    Console.WriteLine(d.Key.ToString() + ":\t" + d.Value.ToString());
}

7
  // Create a ResXResourceReader for the file items.resx.
  ResXResourceReader rsxr = new ResXResourceReader("items.resx");

  // Create an IDictionaryEnumerator to iterate through the resources.
  IDictionaryEnumerator id = rsxr.GetEnumerator();       

  // Iterate through the resources and display the contents to the console.
  foreach (DictionaryEntry d in rsxr) 
  {
Console.WriteLine(d.Key.ToString() + ":\t" + d.Value.ToString());
  }

 //Close the reader.
 rsxr.Close();

voir le lien: exemple Microsoft


4
Notez que cette classe est dans l' System.Windows.Formsassembly et n'est pas automatiquement ajoutée si vous utilisez une application MVC
Rob Scott

6

À la minute où vous ajoutez un fichier .RESX de ressource à votre projet, Visual Studio crée un Designer.cs avec le même nom, créant une classe pour vous avec tous les éléments de la ressource en tant que propriétés statiques. Vous pouvez voir tous les noms de la ressource lorsque vous tapez le point dans l'éditeur après avoir tapé le nom du fichier de ressources.

Vous pouvez également utiliser la réflexion pour parcourir ces noms.

Type resourceType = Type.GetType("AssemblyName.Resource1");
PropertyInfo[] resourceProps = resourceType.GetProperties(
    BindingFlags.NonPublic | 
    BindingFlags.Static | 
    BindingFlags.GetProperty);

foreach (PropertyInfo info in resourceProps)
{
    string name = info.Name;
    object value = info.GetValue(null, null);  // object can be an image, a string whatever
    // do something with name and value
}

Cette méthode n'est évidemment utilisable que lorsque le fichier RESX est dans la portée de l'assembly ou du projet en cours. Sinon, utilisez la méthode fournie par "pulse".

L'avantage de cette méthode est que vous appelez les propriétés réelles qui vous ont été fournies, en tenant compte de toute localisation si vous le souhaitez. Cependant, il est plutôt redondant, car vous devez normalement utiliser la méthode directe de type safe pour appeler les propriétés de vos ressources.


2
Pourquoi utiliser la réflexion quand un ResourceSet est disponible?
Oundless

C'est ce que je me demande aussi (voir le dernier paragraphe). Je voulais juste montrer une méthode alternative, mais plus important encore, je voulais montrer que la classe est entièrement accessible et que vous n'avez pas besoin de faire de magie à la main (le premier paragraphe).
Abel


1

Si vous souhaitez utiliser LINQ, utilisez resourceSet.OfType<DictionaryEntry>(). L'utilisation de LINQ vous permet, par exemple, de sélectionner des ressources en fonction de leur index (int) au lieu de la clé (chaîne):

ResourceSet resourceSet = Resources.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
foreach (var entry in resourceSet.OfType<DictionaryEntry>().Select((item, i) => new { Index = i, Key = item.Key, Value = item.Value }))
{
    Console.WriteLine(@"[{0}] {1}", entry.Index, entry.Key);
}

1

Avec le package nuget System.Resources.ResourceManager(v4.3.0) le ResourceSetetResourceManager.GetResourceSet ne sont pas disponibles.

Utilisation de ResourceReader, comme le suggère cet article: " C # - Impossible d'obtenir une chaîne de ResourceManager (à partir de l'assembly satellite) "

Il est toujours possible de lire les clés / valeurs du fichier de ressources.

System.Reflection.Assembly resourceAssembly = System.Reflection.Assembly.Load(new System.Reflection.AssemblyName("YourAssemblyName"));
String[] manifests = resourceAssembly.GetManifestResourceNames(); 
using (ResourceReader reader = new ResourceReader(resourceAssembly.GetManifestResourceStream(manifests[0])))
{
   System.Collections.IDictionaryEnumerator dict = reader.GetEnumerator();
   while (dict.MoveNext())
   {
      String key = dict.Key as String;
      String value = dict.Value as String;
   }
}

0

Utilisation de LINQ to SQL :

XDocument
        .Load(resxFileName)
        .Descendants()
        .Where(_ => _.Name == "data")
        .Select(_ => $"{ _.Attributes().First(a => a.Name == "name").Value} - {_.Value}");

0

Boucle de lecture simple utiliser ce code

var resx = ResourcesName.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, false, false);

foreach (DictionaryEntry dictionaryEntry in resx)
{
    Console.WriteLine("Key: " + dictionaryEntry.Key);
    Console.WriteLine("Val: " + dictionaryEntry.Value);
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.