Перегляньте всі ресурси у файлі .resx


125

Чи є спосіб прокрутити всі ресурси у .resxфайлі на C #?


2
Чи можете ви детально розглянути питання про те, чи є файл RESX внутрішнім у вашому проекті чи потрібно (чи потрібно) прочитати окремий файл RESX чи прочитати RESX з іншої збірки?
Авель

Відповіді:


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

3
Лінія Джофлетча насправді допомогла мені. У мене був resx, розташований в іншому проекті C #, тому його рядок дозволив мені зателефонувати на цю dll-збірку та завантажувати в ресурси таким чином. Крім того, коли я спробував включити PageList у свій код, він видав помилку для PageList.ResourceManager .. сказавши, що "PageList не містить визначення ResourceManager". І нарешті, string resourceKey = entry.Key кинув помилку, я використав замість "object resourceKey = entry.Key"
sksallaj

2
Залежно від того, чи є у вас фактично визначені культури на вашому ресурсі, вам доведеться перейти на CultureInfo.InvariantCulture. Тут я використовував ресурси в бібліотеці, а не програму WinForms.
Ізраїль Лопес

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

див. посилання: приклад мікрософт


4
Зауважте, що цей клас є у складі System.Windows.Formsі не додається автоматично, якщо ви використовуєте додаток MVC
Роб Скотт

6

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

Крім того, ви можете використовувати відображення для перегляду цих імен.

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?
Безвісти

Про це я також здивувався (див. Останній абзац). Просто хотів показати альтернативний метод, але, що ще важливіше, хотів показати, що клас зроблений повністю доступним і вам не потрібно робити ніяких чарів вручну (перший абзац).
Авель


1

Якщо ви хочете використовувати LINQ, використовуйте resourceSet.OfType<DictionaryEntry>(). Використання LINQ дозволяє, наприклад, вибирати ресурси на основі їх індексу (int) замість ключа (рядка):

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

З пакетом nuget System.Resources.ResourceManager(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.