Scorri tutte le risorse in un file .resx


125

C'è un modo per scorrere tutte le risorse in un .resxfile in C #?


2
Puoi approfondire se il file RESX è interno al tuo progetto o se vuoi (o devi) leggere un file RESX separato o leggere RESX da un altro assembly?
Abel,

Risposte:


243

Utilizzare sempre il gestore risorse e non leggere direttamente i file per assicurarsi che la globalizzazione sia presa in considerazione.

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
Mi ci è voluto un po 'per capire che hai bisogno di questa linea per dichiarare MyResourceClass. ResourceManager MyResourceClass = new ResourceManager("Resources.ResourceFileName", System.Reflection.Assembly.Load("App_GlobalResources"));
JoeFletch,

6
@JoeFletch: questa linea non ha bisogno. Il codice chiama direttamente il file di risorse. Esempio: ho un file chiamato PageList.resx, quindi chiamerò: ResourceSet resourceSet = PageList.ResourceManager.GetResourceSet (CultureInfo.CurrentUICulture, true, true);
Gabriel,

@Gabriel, grazie per l'aggiornamento! Dovrò tornare al mio codice per verificarlo.
JoeFletch,

3
La linea di JoeFletch mi ha davvero aiutato. Avevo un resx in un altro progetto C #, quindi la sua linea mi ha permesso di chiamare quell'assembly dll e caricare le risorse in quel modo. Inoltre, quando ho provato a includere il PageList nel mio codice, ha generato un errore per PageList.ResourceManager .. dicendo "Il PageList non contiene una definizione per ResourceManager". E infine, stringa resourceKey = entry.Key ha generato un errore, ho usato invece "object resourceKey = entry.Key"
sksallaj

2
A seconda che tu abbia effettivamente culture definite nella tua risorsa, dovrai passare a CultureInfo.InvariantCulture. Qui stavo usando le risorse in una libreria, non in un'app WinForms.
Israel Lopez,

26

Bloggato a riguardo sul mio blog :) La versione breve è, per trovare i nomi completi delle risorse (a meno che tu non le conosca già):

var assembly = Assembly.GetExecutingAssembly();

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

Per usarli tutti per qualcosa:

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

Per utilizzare risorse in altri assembly diversi da quello in esecuzione, è sufficiente ottenere un oggetto assembly diverso utilizzando alcuni degli altri metodi statici della Assemblyclasse. Spero che sia d'aiuto :)


Puoi enumerare le risorse che non si trovano in una cartella denominata "Risorsa"? Vorrei enumerare tutte le immagini di risorse presenti nel mio progetto in una cartella denominata "Immagini".
Simon Bosley,

Abbastanza sicuro che non gli importa di dove si trova? Provalo?
Svish,

1
Avevo file in una cartella per importare file sql e questo ha funzionato perfettamente. Ho aggiunto una conversione da un flusso a stringa in modo da poter leggere il file e non ho avuto problemi.
ErocM,

9

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

vedi link: esempio microsoft


4
Si noti che questa classe è System.Windows.Formsnell'assembly e non viene aggiunta automaticamente se si utilizza un'app MVC
Rob Scott,

6

Nel momento in cui aggiungi un file .RESX di risorsa al tuo progetto, Visual Studio creerà un Designer.cs con lo stesso nome, creando una classe per te con tutti gli elementi della risorsa come proprietà statiche. È possibile visualizzare tutti i nomi della risorsa quando si digita il punto nell'editor dopo aver digitato il nome del file di risorse.

In alternativa, puoi usare la riflessione per scorrere questi nomi.

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
}

Questo metodo è ovviamente utilizzabile solo quando il file RESX rientra nell'ambito dell'assembly o del progetto corrente. In caso contrario, utilizzare il metodo fornito da "pulse".

Il vantaggio di questo metodo è che chiamate le proprietà reali che sono state fornite per voi, tenendo conto di qualsiasi localizzazione, se lo desiderate. Tuttavia, è piuttosto ridondante, poiché normalmente dovresti usare il metodo type safe direct per chiamare le proprietà delle tue risorse.


2
Perché usare la riflessione quando è disponibile un ResourceSet?
Oundless

È quello che mi chiedo anche io (vedi l'ultimo paragrafo). Volevo solo mostrare un metodo alternativo, ma, soprattutto, volevo dimostrare che la classe è resa completamente accessibile e che non è necessario eseguire alcuna magia a mano (il primo paragrafo).
Abel,


1

Se si desidera utilizzare LINQ, utilizzare resourceSet.OfType<DictionaryEntry>(). L'uso di LINQ consente, ad esempio, di selezionare le risorse in base al loro indice (int) anziché alla chiave (stringa):

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

Con il pacchetto nuget System.Resources.ResourceManager(v4.3.0) il ResourceSete ResourceManager.GetResourceSetnon sono disponibili.

Usando il ResourceReader, come suggerisce questo post: " C # - Impossibile ottenere una stringa da ResourceManager (dall'assemblaggio satellite) "

È ancora possibile leggere la chiave / i valori del file di risorse.

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

Utilizzando LINQ to SQL :

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

0

Il ciclo di lettura semplice utilizza questo codice

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

foreach (DictionaryEntry dictionaryEntry in resx)
{
    Console.WriteLine("Key: " + dictionaryEntry.Key);
    Console.WriteLine("Val: " + dictionaryEntry.Value);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.