Перебрать все ресурсы в 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;
}

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класса. Надеюсь, поможет :)


Можете ли вы перечислить ресурсы, не находящиеся в папке под названием «Ресурс»? Я хочу перечислить все изображения ресурсов, расположенные в моем проекте, в папке под названием «Изображения».
— Саймон Босли

Совершенно уверен, что его не волнует, где он находится? Попробуй это?
— Свиш

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


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

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

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

foreach (DictionaryEntry dictionaryEntry in resx)
{
    Console.WriteLine("Key: " + dictionaryEntry.Key);
    Console.WriteLine("Val: " + dictionaryEntry.Value);
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.