Ulangi semua sumber daya dalam file .resx


125

Apakah ada cara untuk mengulang semua sumber daya dalam .resxfile di C #?


2
Bisakah Anda menguraikan apakah file RESX internal untuk proyek Anda atau apakah Anda ingin (atau perlu) membaca file RESX terpisah atau membaca RESX dari majelis lain?
Abel

Jawaban:


243

Anda harus selalu menggunakan manajer sumber daya dan tidak membaca file secara langsung untuk memastikan globalisasi diperhitungkan.

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
Saya perlu sedikit waktu untuk mengetahui bahwa Anda perlu baris ini untuk mendeklarasikan MyResourceClass. ResourceManager MyResourceClass = new ResourceManager("Resources.ResourceFileName", System.Reflection.Assembly.Load("App_GlobalResources"));
JoeFletch

6
@ JoFletch: tidak perlu baris ini. Kode ini memanggil File Sumber Daya secara langsung. Contoh: saya punya file bernama PageList.resx, maka saya akan memanggil: ResourceSet resourceSet = PageList.ResourceManager.GetResourceSet (CultureInfo.CurrentUICulture, true, true);
Gabriel

@Gabriel, terima kasih atas pembaruannya! Saya harus kembali ke kode saya untuk memeriksanya.
JoeFletch

3
Garis JoeFletch sebenarnya membantu saya. Saya punya resx di terletak di proyek C # lain, jadi garisnya memungkinkan saya untuk memanggil perakitan dll dan memuat sumber daya seperti itu. Juga, ketika saya mencoba untuk memasukkan PageList pada kode saya, itu melemparkan kesalahan untuk PageList.ResourceManager .. mengatakan "PageList tidak mengandung definisi untuk ResourceManager". Dan akhirnya, string resourceKey = entry.Key melemparkan kesalahan, saya menggunakan "object resourceKey = entry.Key" sebagai
gantinya

2
Bergantung jika Anda benar-benar memiliki budaya yang ditentukan dalam sumber daya Anda, Anda harus beralih ke CultureInfo.InvariantCulture. Di sini saya menggunakan sumber daya di perpustakaan, bukan aplikasi WinForms.
Israel Lopez

26

Blogged tentang hal itu di blog saya :) Versi singkatnya adalah, untuk menemukan nama lengkap sumber daya (kecuali Anda sudah mengetahuinya):

var assembly = Assembly.GetExecutingAssembly();

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

Untuk menggunakan semuanya untuk sesuatu:

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

Untuk menggunakan sumber daya di rakitan lain daripada yang sedang dieksekusi, Anda hanya akan mendapatkan objek rakitan yang berbeda dengan menggunakan beberapa metode statis lain di Assemblykelas. Semoga bermanfaat :)


Bisakah Anda menyebutkan sumber daya yang tidak terdapat di folder bernama 'Sumber Daya'? Saya ingin menghitung semua gambar sumber daya yang terletak di proyek saya di folder bernama 'Gambar'.
Simon Bosley

Cukup yakin itu tidak peduli di mana lokasinya? Menguji?
Svish

1
Saya punya file dalam folder untuk inporting file sql dan ini berfungsi dengan baik. Saya menambahkan konversi dari aliran ke string sehingga saya bisa membaca file dan tidak memiliki masalah.
ErocM

9

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

lihat tautan: contoh microsoft


4
Perhatikan bahwa kelas ini ada dalam System.Windows.Formsperakitan dan tidak secara otomatis ditambahkan jika Anda menggunakan aplikasi MVC
Rob Scott

6

Begitu Anda menambahkan file .RESX sumber daya ke proyek Anda, Visual Studio akan membuat Designer.cs dengan nama yang sama, menciptakan kelas untuk Anda dengan semua item sumber daya sebagai properti statis. Anda bisa melihat semua nama sumber daya saat Anda mengetik titik di editor setelah Anda mengetik nama file sumber daya.

Atau, Anda dapat menggunakan refleksi untuk mengulangi nama-nama ini.

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
}

Metode ini jelas hanya dapat digunakan ketika file RESX berada dalam lingkup perakitan atau proyek saat ini. Kalau tidak, gunakan metode yang disediakan oleh "pulsa".

Keuntungan dari metode ini adalah Anda memanggil properti aktual yang telah disediakan untuk Anda, dengan mempertimbangkan lokalisasi apa pun jika Anda mau. Namun, ini agak berlebihan, karena biasanya Anda harus menggunakan metode safe type langsung untuk memanggil properti dari sumber daya Anda.


2
Mengapa menggunakan refleksi ketika tersedia ResourceSet?
Oundless

Itulah yang saya ingin tahu juga (lihat paragraf terakhir). Hanya ingin menunjukkan metode alternatif, tetapi yang lebih penting, ingin menunjukkan bahwa kelas dibuat sepenuhnya dapat diakses dan Anda tidak perlu melakukan sihir dengan tangan (paragraf pertama).
Abel


1

Jika Anda ingin menggunakan LINQ, gunakan resourceSet.OfType<DictionaryEntry>(). Menggunakan LINQ memungkinkan Anda, misalnya, untuk memilih sumber daya berdasarkan indeks (int) mereka daripada kunci (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

Dengan paket System.Resources.ResourceManagernuget (v4.3.0) ResourceSetdanResourceManager.GetResourceSet tidak tersedia.

Menggunakan ResourceReader, seperti yang disarankan oleh pos ini: " C # - Tidak dapat memperoleh string dari ResourceManager (dari perakitan satelit) "

Masih mungkin untuk membaca kunci / nilai file sumber daya.

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

Menggunakan LINQ ke SQL :

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

0

Baca lingkaran sederhana menggunakan kode ini

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

foreach (DictionaryEntry dictionaryEntry in resx)
{
    Console.WriteLine("Key: " + dictionaryEntry.Key);
    Console.WriteLine("Val: " + dictionaryEntry.Value);
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.