Repetir todos os recursos em um arquivo .resx


125

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


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

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 :)


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

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


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.


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

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

0

Usando LINQ to SQL :

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

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);
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.