2010-01-11 21 views
111

Có cách nào để lặp qua tất cả các tài nguyên trong tệp .resx trong C# không?Lặp qua tất cả các tài nguyên trong một tệp .resx

+1

Bạn có thể giải thích xem tệp RESX có nằm trong dự án của bạn hay bạn muốn (hoặc cần phải) đọc một tệp RESX riêng biệt hoặc đọc RESX từ một hội đồng khác? – Abel

Trả lời

211

Bạn nên luôn sử dụng trình quản lý tài nguyên và không đọc tệp trực tiếp để đảm bảo tính toàn cầu hóa được tính đến.

using System.Collections; 
using System.Globalization; 
using System.Resources; 

... 


     ResourceManager MyResourceClass = new ResourceManager(typeof(Resources /* Reference to your resources class -- may be named differently in your case */)); 

ResourceSet resourceSet = MyResourceClass.ResourceManager.GetResourceSet(CultureInfo.CurrentUICulture, true, true); 
foreach (DictionaryEntry entry in resourceSet) 
{ 
    string resourceKey = entry.Key.ToString(); 
    object resource = entry.Value; 
} 
+12

Nó đã cho tôi một chút để tìm ra rằng bạn cần dòng này để khai báo MyResourceClass. 'ResourceManager MyResourceClass = new ResourceManager (" Resources.ResourceFileName ", System.Reflection.Assembly.Load (" App_GlobalResources "));' – JoeFletch

+6

@JoeFletch: nó không cần dòng này. Mã này gọi trực tiếp tệp tài nguyên. Ví dụ: tôi có một tệp có tên PageList.resx, sau đó tôi sẽ gọi: ResourceSet resourceSet = PageList.ResourceManager.GetResourceSet (CultureInfo.CurrentUICulture, đúng, đúng); – Gabriel

+0

@Gabriel, cảm ơn bạn đã cập nhật! Tôi sẽ phải quay lại mã của tôi để kiểm tra điều này. – JoeFletch

7

Sử dụng ResXResourceReader Class

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

viết blog về nó on my blog :) phiên bản ngắn là, để tìm ra tên đầy đủ của các nguồn tài nguyên (trừ khi bạn đã biết chúng):

var assembly = Assembly.GetExecutingAssembly(); 

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

Để sử dụng tất cả trong số họ cho một cái gì đó:

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

Để sử dụng tài nguyên trong các hội đồng khác so với thực thi, bạn chỉ cần có đối tượng lắp ráp khác bằng cách sử dụng một số phương pháp tĩnh khác của lớp Assembly. Hy vọng nó giúp :)

+0

Bạn có thể liệt kê tài nguyên * không * nằm trong một thư mục có tên 'Tài nguyên' không? Tôi muốn liệt kê tất cả các hình ảnh tài nguyên nằm trong dự án của tôi trong một thư mục có tên là 'Hình ảnh'. –

+0

Khá chắc chắn nó không quan tâm về vị trí của nó? Kiểm tra nó? – Svish

+1

Tôi đã có các tệp trong một thư mục để nhập tệp sql và điều này hoạt động hoàn hảo. Tôi đã thêm chuyển đổi từ luồng thành chuỗi nên tôi có thể đọc tệp và không có vấn đề gì. – ErocM

5

Phút bạn thêm tệp .RESX vào dự án của bạn, Visual Studio sẽ tạo một Designer.cs có cùng tên, tạo lớp aa cho bạn với tất cả các mục của tài nguyên dưới dạng thuộc tính tĩnh . Bạn có thể xem tất cả tên của tài nguyên khi bạn nhập dấu chấm trong trình chỉnh sửa sau khi bạn nhập tên của tệp tài nguyên.

Hoặc, bạn có thể sử dụng phản chiếu để lặp qua các tên này.

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 
} 

Phương pháp này rõ ràng chỉ có thể sử dụng khi tệp RESX nằm trong phạm vi của hội đồng hoặc dự án hiện tại. Nếu không, hãy sử dụng phương thức được cung cấp bởi "xung".

Ưu điểm của phương pháp này là bạn gọi các thuộc tính thực tế đã được cung cấp cho bạn, có tính đến bất kỳ nội địa hóa nào nếu bạn muốn. Tuy nhiên, nó là khá dư thừa, như thường lệ, bạn nên sử dụng loại phương pháp trực tiếp an toàn gọi các thuộc tính của tài nguyên của bạn.

+2

Tại sao phải sử dụng sự phản chiếu khi có sẵn một ResourceSet? –

+0

Đó là những gì tôi tự hỏi là tốt (xem đoạn cuối). Chỉ muốn thể hiện một phương pháp thay thế, nhưng quan trọng hơn, muốn cho thấy rằng lớp học được thực hiện hoàn toàn có thể truy cập được và bạn không cần thực hiện bất kỳ phép thuật nào bằng tay (đoạn đầu tiên). – Abel

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

xem liên kết: microsoft example

+3

Lưu ý rằng lớp này nằm trong tập hợp 'System.Windows.Forms' và không tự động được thêm nếu bạn đang sử dụng ứng dụng MVC –

0

Sử dụng LINQ to SQL:

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

Nếu bạn muốn sử dụng LINQ, sử dụng resourceSet.OfType<DictionaryEntry>(). Sử dụng LINQ cho phép bạn, ví dụ, để chọn tài nguyên dựa trên chỉ mục của họ (int) thay vì khóa (chuỗi):

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); 
} 
Các vấn đề liên quan