Перебрать все ресурсы в RESX-файле

126

Есть ли способ перебрать все ресурсы в .resxфайле на C #?

нп.
источник
2
Можете ли вы уточнить, является ли файл RESX внутренним для вашего проекта, или вы хотите (или должны) читать отдельный файл RESX или читать RESX из другой сборки?
Abel

Ответы:

243

Вы всегда должны использовать диспетчер ресурсов и не читать файлы напрямую, чтобы обеспечить учет глобализации.

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
источник
12
Мне потребовалось немного времени, чтобы понять, что вам нужна эта строка для объявления MyResourceClass. ResourceManager MyResourceClass = new ResourceManager("Resources.ResourceFileName", System.Reflection.Assembly.Load("App_GlobalResources"));
JoeFletch
6
@JoeFletch: ему не нужна эта строка. Код напрямую вызывает файл ресурсов. Пример: у меня есть файл с именем PageList.resx, тогда я вызываю: ResourceSet resourceSet = PageList.ResourceManager.GetResourceSet (CultureInfo.CurrentUICulture, true, true);
Габриэль
@Gabriel, спасибо за обновление! Мне придется вернуться к своему коду, чтобы проверить это.
JoeFletch 06
3
Линия Джо Флетча действительно выручила меня. У меня был файл resx, расположенный в другом проекте C #, поэтому его строка позволила мне вызвать эту сборку dll и таким образом загрузить ресурсы. Кроме того, когда я пытался включить PageList в свой код, он выдавал ошибку для PageList.ResourceManager ... говоря, что «PageList не содержит определения для ResourceManager». И, наконец, строка resourceKey = entry.Key вызвала ошибку, вместо этого я использовал «object resourceKey = entry.Key»
sksallaj 06
2
В зависимости от того, действительно ли в вашем ресурсе определены культуры, вам придется переключиться на CultureInfo.InvariantCulture. Здесь я использовал ресурсы в библиотеке, а не в приложении WinForms.
Israel Lopez
26

Об этом писал в своем блоге :) Краткая версия, чтобы найти полные названия ресурсов (если вы их еще не знаете):

var assembly = Assembly.GetExecutingAssembly();

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

Чтобы использовать их все для чего-нибудь:

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

Чтобы использовать ресурсы в сборках, отличных от исполняемой, вы просто получите другой объект сборки, используя некоторые из других статических методов Assemblyкласса. Надеюсь, поможет :)

Svish
источник
Можете ли вы перечислить ресурсы, не находящиеся в папке под названием «Ресурс»? Я хочу перечислить все изображения ресурсов, расположенные в моем проекте, в папке под названием «Изображения».
Саймон Босли
Совершенно уверен, что его не волнует, где он находится? Попробуй это?
Свиш
1
У меня были файлы в папке для импорта файлов sql, и это отлично сработало. Я добавил преобразование из потока в строку, чтобы я мог читать файл и не имел проблем.
ErocM
9

Используйте класс 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();

см. ссылку: пример Microsoft

logicfalse
источник
4
Обратите внимание, что этот класс находится в System.Windows.Formsсборке и не добавляется автоматически, если вы используете приложение MVC
Роб Скотт,
6

В тот момент, когда вы добавляете файл ресурса .RESX в свой проект, Visual Studio создает файл Designer.cs с тем же именем, создавая для вас класс со всеми элементами ресурса в качестве статических свойств. Вы можете увидеть все имена ресурса, если наберете точку в редакторе после того, как наберете имя файла ресурса.

В качестве альтернативы вы можете использовать отражение для циклического перебора этих имен.

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
}

Очевидно, что этот метод можно использовать только в том случае, если файл RESX находится в рамках текущей сборки или проекта. В противном случае используйте метод, предоставленный «импульсом».

Преимущество этого метода в том, что вы вызываете фактические свойства, которые были предоставлены для вас, с учетом любой локализации, если хотите. Однако это довольно избыточно, поскольку обычно вы должны использовать безопасный для типов прямой метод вызова свойств ваших ресурсов.

Абель
источник
2
Зачем использовать отражение, когда доступен ResourceSet?
Oundless
Это то, что мне тоже интересно (см. Последний абзац). Просто хотел показать альтернативный метод, но, что более важно, хотел показать, что класс сделан полностью доступным, и вам не нужно творить магию вручную (первый абзац).
Abel
1

Если вы хотите использовать LINQ, используйте resourceSet.OfType<DictionaryEntry>(). Использование LINQ позволяет, например, выбирать ресурсы по их индексу (int) вместо ключа (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

В пакете System.Resources.ResourceManagernuget (v4.3.0) функции ResourceSetи ResourceManager.GetResourceSetнедоступны.

Использование ResourceReader, как предлагается в этом сообщении: « C # - Невозможно получить строку из ResourceManager (из вспомогательной сборки) »

По-прежнему можно прочитать ключи / значения файла ресурсов.

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

Использование LINQ to SQL :

XDocument
        .Load(resxFileName)
        .Descendants()
        .Where(_ => _.Name == "data")
        .Select(_ => $"{ _.Attributes().First(a => a.Name == "name").Value} - {_.Value}");
Андрей Толстой
источник
0

Простой цикл чтения используйте этот код

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

foreach (DictionaryEntry dictionaryEntry in resx)
{
    Console.WriteLine("Key: " + dictionaryEntry.Key);
    Console.WriteLine("Val: " + dictionaryEntry.Value);
}
Аже Кун
источник