Repetir todos os recursos em um arquivo .resx

125

Existe uma maneira de percorrer todos os recursos em um .resxarquivo em c #?

np.
fonte
2
Você pode saber se o arquivo RESX é interno ao seu projeto ou se deseja (ou precisa) ler um arquivo RESX separado ou ler o RESX de outra montagem?
Abel

Respostas:

243

Você sempre deve usar o gerenciador de recursos e não ler arquivos diretamente para garantir que a globalização seja levada em consideração.

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;
}
Oundless
fonte
12
Demorei um pouco para descobrir que você precisa dessa linha para declarar MyResourceClass. ResourceManager MyResourceClass = new ResourceManager("Resources.ResourceFileName", System.Reflection.Assembly.Load("App_GlobalResources"));
JoeFletch
6
@ JoeFletch: não precisa dessa linha. O código chama o arquivo de recurso diretamente. Exemplo: eu tenho um arquivo chamado PageList.resx, então chamarei: ResourceSet resourceSet = PageList.ResourceManager.GetResourceSet (CultureInfo.CurrentUICulture, true, true);
6113 Gabriel
@ Gabriel, obrigado pela atualização! Vou ter que voltar ao meu código para verificar isso.
21813 JoeFletch
3
A linha de JoeFletch realmente me ajudou. Eu tinha um resx localizado em outro projeto C #, então a linha dele me permitiu chamar esse assembly dll e carregar os recursos dessa maneira. Além disso, quando tentei incluir o PageList no meu código, ele gerou um erro para o PageList.ResourceManager .. dizendo "PageList não contém uma definição para o ResourceManager". E, finalmente, corda resourceKey = entry.Key jogou um erro, eu usei vez "objeto resourceKey = entry.Key"
sksallaj
2
Dependendo se você realmente tem culturas definidas em seu recurso, será necessário alternar para CultureInfo.InvariantCulture. Aqui eu estava usando recursos em uma biblioteca, não em um aplicativo WinForms.
Israel Lopez
26

Blogue sobre isso no meu blog :) A versão curta é: para encontrar os nomes completos dos recursos (a menos que você já os conheça):

var assembly = Assembly.GetExecutingAssembly();

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

Para usar todos eles para alguma coisa:

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

Para usar recursos em outros assemblies que não o de execução, você apenas obteria um objeto de assembly diferente usando alguns dos outros métodos estáticos da Assemblyclasse. Espero que ajude :)

Svish
fonte
Você pode enumerar recursos não localizados em uma pasta chamada 'Recurso'? Eu gostaria de enumerar todas as imagens de recursos localizadas no meu projeto em uma pasta chamada 'Imagens'.
Simon Bosley
Certeza de que ele não se importa com a localização? Teste-o?
Svish
1
Eu tinha arquivos em uma pasta para transportar arquivos sql e isso funcionou perfeitamente. Adicionei uma conversão de um fluxo para uma string para poder ler o arquivo e não ter problemas.
ErocM 23/08/16
9

Use a 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());
}
rahul
fonte
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();

veja o link: exemplo da microsoft

logicfalse
fonte
4
Note-se que esta classe é na System.Windows.Formsmontagem e não é adicionada automaticamente se você estiver usando um aplicativo MVC
Rob Scott
6

No minuto em que você adiciona um arquivo .RESX ao seu projeto, o Visual Studio cria um Designer.cs com o mesmo nome, criando uma classe para você com todos os itens do recurso como propriedades estáticas. Você pode ver todos os nomes do recurso ao digitar o ponto no editor após digitar o nome do arquivo de recurso.

Como alternativa, você pode usar a reflexão para percorrer esses nomes.

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
}

Obviamente, esse método só pode ser usado quando o arquivo RESX estiver no escopo do conjunto ou projeto atual. Caso contrário, use o método fornecido por "pulso".

A vantagem desse método é que você chama as propriedades reais que foram fornecidas para você, levando em consideração qualquer localização, se desejar. No entanto, é bastante redundante, pois normalmente você deve usar o método direto seguro de tipo para chamar as propriedades de seus recursos.

Abel
fonte
2
Por que usar a reflexão quando há um ResourceSet disponível?
Oundless
É isso que eu gostaria de saber também (veja o último parágrafo). Só queria mostrar um método alternativo, mas, mais importante, queria mostrar que a classe é totalmente acessível e você não precisa fazer nenhuma mágica manualmente (o primeiro parágrafo).
Abel
1

Se você deseja usar o LINQ, use resourceSet.OfType<DictionaryEntry>(). O uso do LINQ permite, por exemplo, selecionar recursos com base em seu índice (int) em vez da chave (string):

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);
}
Ron Inbar
fonte
1

Com o pacote System.Resources.ResourceManagernuget (v4.3.0), o ResourceSeteResourceManager.GetResourceSet não está disponível.

Usando o ResourceReader, como sugerido nesta postagem: " C # - Não é possível obter uma string do ResourceManager (do assembly satélite) "

Ainda é possível ler a chave / valores do arquivo de recurso.

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;
   }
}
Jordy
fonte
0

Usando LINQ to SQL :

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

Loop de leitura simples use este código

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

foreach (DictionaryEntry dictionaryEntry in resx)
{
    Console.WriteLine("Key: " + dictionaryEntry.Key);
    Console.WriteLine("Val: " + dictionaryEntry.Value);
}
Azhe Kun
fonte