วนซ้ำทรัพยากรทั้งหมดในไฟล์. 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 จริงจริง);
Gabriel

@ Gabriel ขอบคุณสำหรับการอัปเดต! ฉันจะต้องกลับไปที่รหัสของฉันเพื่อตรวจสอบสิ่งนี้
JoeFletch

3
บรรทัดของ JoeFletch ช่วยฉันได้จริง ฉันมี resx อยู่ในโครงการ C # อื่นดังนั้นสายของเขาจึงอนุญาตให้ฉันเรียกแอสเซมบลี dll นั้นและโหลดทรัพยากรด้วยวิธีนั้น นอกจากนี้เมื่อฉันพยายามรวม PageList ในโค้ดของฉันมันทำให้เกิดข้อผิดพลาดสำหรับ PageList.ResourceManager .. โดยบอกว่า "PageList ไม่มีคำจำกัดความสำหรับ ResourceManager" และในที่สุด string resourceKey = entry.Key เกิดข้อผิดพลาดฉันใช้แทน "object resourceKey = entry.Key"
sksallaj

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คลาส หวังว่าจะช่วยได้ :)


คุณสามารถระบุทรัพยากรที่ไม่ได้อยู่ในโฟลเดอร์ชื่อ 'ทรัพยากร' ได้หรือไม่? ฉันต้องการระบุรูปภาพทรัพยากรทั้งหมดที่อยู่ในโครงการของฉันในโฟลเดอร์ชื่อ "รูปภาพ"
Simon Bosley

ค่อนข้างแน่ใจว่ามันไม่สนใจว่ามันจะอยู่ที่ไหน? ทดสอบไหม
Svish

1
ฉันมีไฟล์ในโฟลเดอร์สำหรับนำเข้าไฟล์ sql และมันก็ทำงานได้อย่างสมบูรณ์แบบ ฉันเพิ่มการแปลงจากสตรีมเป็นสตริงดังนั้นฉันจึงสามารถอ่านไฟล์ได้และไม่มีปัญหา
ErocM


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
Rob Scott

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 อยู่ในขอบเขตของแอสเซมบลีหรือโปรเจ็กต์ปัจจุบัน มิฉะนั้นให้ใช้วิธีการ "ชีพจร"

ข้อดีของวิธีนี้คือคุณเรียกคุณสมบัติจริงที่จัดเตรียมไว้ให้คุณโดยคำนึงถึงการแปลเป็นภาษาท้องถิ่นหากคุณต้องการ อย่างไรก็ตามมันค่อนข้างซ้ำซ้อนเนื่องจากโดยปกติคุณควรใช้วิธีการประเภท safe direct ในการเรียกคุณสมบัติของทรัพยากรของคุณ


2
เหตุใดจึงต้องใช้การสะท้อนเมื่อมี ResourceSet พร้อมใช้งาน
Oundless

นั่นคือสิ่งที่ฉันสงสัยเช่นกัน (ดูย่อหน้าสุดท้าย) เพียงแค่ต้องการแสดงวิธีการอื่น แต่ที่สำคัญกว่านั้นคือต้องการแสดงให้เห็นว่าชั้นเรียนนั้นสามารถเข้าถึงได้อย่างเต็มที่และคุณไม่จำเป็นต้องใช้เวทมนตร์ด้วยมือ (ย่อหน้าแรก)
Abel


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);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.