Bagikan melalui


Kelas System.Resources.ResourceReader

Artikel ini menyediakan keterangan tambahan untuk dokumentasi referensi untuk API ini.

Penting

Metode panggilan dari kelas ini dengan data yang tidak tepercaya adalah risiko keamanan. Panggil metode dari kelas ini hanya dengan data tepercaya. Untuk informasi selengkapnya, lihat Memvalidasi Semua Input.

Kelas ResourceReader menyediakan implementasi standar antarmuka IResourceReader. Instans ResourceReader mewakili file .resources yang berdiri sendiri atau file .resources yang disematkan dalam suatu assembly. Ini digunakan untuk menghitung sumber daya dalam file .resources dan mengambil pasangan nama/nilainya. Ini berbeda dari kelas ResourceManager, yang digunakan untuk mengambil sumber daya bernama tertentu dari file .resources yang disematkan dalam assembly. Kelas ResourceManager digunakan untuk mengambil sumber daya yang namanya diketahui sebelumnya, sedangkan kelas ResourceReader berguna untuk mengambil sumber daya yang jumlahnya atau nama yang tepat tidak diketahui pada waktu kompilasi. Misalnya, aplikasi dapat menggunakan file sumber daya untuk menyimpan informasi konfigurasi yang diatur ke dalam bagian dan item di bagian, di mana jumlah bagian atau item di bagian tidak diketahui sebelumnya. Sumber daya kemudian dapat diberi nama secara generik (seperti Section1, Section1Item1, Section1Item2, dan sebagainya) dan diambil dengan menggunakan objek ResourceReader.

Penting

Jenis ini mengimplementasikan antarmuka IDisposable. Setelah selesai menggunakan jenis tersebut, Anda harus menyingkirkannya baik secara langsung maupun tidak langsung. Untuk meniadakan tipe secara langsung, panggil metode Dispose dalam blok try/catch. Untuk membuangnya secara tidak langsung, gunakan konstruksi bahasa seperti using (dalam C#) atau Using (di Visual Basic). Untuk informasi selengkapnya, lihat bagian "Menggunakan Objek yang Menerapkan IDisposable" di dokumentasi antarmuka IDisposable.

Membuat objek ResourceReader

File .resources adalah file biner yang telah dikompilasi dari file teks atau file XML .resx dengan Resgen.exe (Resource File Generator). Objek ResourceReader dapat mewakili file .resources mandiri atau file .resources yang telah disematkan dalam rakitan.

Untuk membuat instans objek ResourceReader yang membaca dari file .resources mandiri, gunakan konstruktor kelas ResourceReader dengan aliran input atau string yang berisi nama file .resources. Contoh berikut mengilustrasikan kedua pendekatan. Yang pertama membuat instans objek ResourceReader yang mewakili file .resources bernama Resources1.resources dengan menggunakan nama filenya. Yang kedua membuat instans objek ResourceReader yang mewakili file .resources bernama Resources2.resources dengan menggunakan aliran yang dibuat dari file.

// Instantiate a standalone .resources file from its filename.
var rr1 = new System.Resources.ResourceReader("Resources1.resources");

// Instantiate a standalone .resources file from a stream.
var fs = new System.IO.FileStream(@".\Resources2.resources",
                                  System.IO.FileMode.Open);
var rr2 = new System.Resources.ResourceReader(fs);
' Instantiate a standalone .resources file from its filename.
Dim rr1 As New System.Resources.ResourceReader("Resources1.resources")

' Instantiate a standalone .resources file from a stream.
Dim fs As New System.IO.FileStream(".\Resources2.resources",
                                   System.IO.FileMode.Open)
Dim rr2 As New System.Resources.ResourceReader(fs)

Untuk membuat objek ResourceReader yang mewakili file .resources yang disematkan, buat objek Assembly dari assembly tempat file .resources disematkan. Metode Assembly.GetManifestResourceStream mengembalikan objek Stream yang dapat diteruskan ke konstruktor ResourceReader(Stream). Contoh berikut membuat instans objek ResourceReader yang mewakili file .resources yang disematkan.

System.Reflection.Assembly assem =
             System.Reflection.Assembly.LoadFrom(@".\MyLibrary.dll");
System.IO.Stream fs =
             assem.GetManifestResourceStream("MyCompany.LibraryResources.resources");
var rr = new System.Resources.ResourceReader(fs);
Dim assem As System.Reflection.Assembly = 
             System.Reflection.Assembly.LoadFrom(".\MyLibrary.dll") 
Dim fs As System.IO.Stream = 
             assem.GetManifestResourceStream("MyCompany.LibraryResources.resources")
Dim rr As New System.Resources.ResourceReader(fs)

Menghitung sumber daya objek ResourceReader

Untuk menghitung sumber daya dalam file .resources, Anda memanggil metode GetEnumerator, yang mengembalikan objek System.Collections.IDictionaryEnumerator. Anda memanggil metode IDictionaryEnumerator.MoveNext untuk berpindah dari satu sumber daya ke sumber daya berikutnya. Metode mengembalikan false ketika semua sumber daya dalam file .resources telah dijumlahkan.

Nota

Meskipun kelas ResourceReader mengimplementasikan antarmuka IEnumerable dan metode IEnumerable.GetEnumerator, metode ResourceReader.GetEnumerator tidak menyediakan implementasi IEnumerable.GetEnumerator. Sebagai gantinya, metode ResourceReader.GetEnumerator mengembalikan objek antarmuka IDictionaryEnumerator yang menyediakan akses ke setiap pasangan nama/nilai sumber daya.

Anda dapat mengambil sumber daya individual dalam koleksi dengan dua cara:

  • Anda dapat melakukan iterasi setiap sumber daya dalam koleksi System.Collections.IDictionaryEnumerator dan menggunakan properti System.Collections.IDictionaryEnumerator untuk mengambil nama dan nilai sumber daya. Kami merekomendasikan teknik ini ketika semua sumber daya memiliki jenis yang sama, atau Anda mengetahui jenis data setiap sumber daya.

  • Anda dapat mengambil nama setiap sumber daya saat melakukan iterasi koleksi System.Collections.IDictionaryEnumerator dan memanggil metode GetResourceData untuk mengambil data sumber daya. Kami merekomendasikan pendekatan ini ketika Anda tidak mengetahui jenis data setiap sumber daya atau jika pendekatan sebelumnya melemparkan pengecualian.

Mengambil sumber daya dengan menggunakan properti IDictionaryEnumerator

Metode pertama untuk menghitung sumber daya dalam file .resources melibatkan pengambilan langsung setiap pasangan nama/nilai sumber daya. Setelah Anda memanggil metode IDictionaryEnumerator.MoveNext untuk berpindah ke setiap sumber daya dalam koleksi, Anda dapat mengambil nama sumber daya dari properti IDictionaryEnumerator.Key dan data sumber daya dari properti IDictionaryEnumerator.Value.

Contoh berikut menunjukkan cara mengambil nama dan nilai setiap sumber daya dalam file .resources dengan menggunakan properti IDictionaryEnumerator.Key dan IDictionaryEnumerator.Value. Untuk menjalankan contoh, buat file teks berikut bernama ApplicationResources.txt untuk menentukan sumber daya string.

Title="Contact Information"
Label1="First Name:"
Label2="Middle Name:"
Label3="Last Name:"
Label4="SSN:"
Label5="Street Address:"
Label6="City:"
Label7="State:"
Label8="Zip Code:"
Label9="Home Phone:"
Label10="Business Phone:"
Label11="Mobile Phone:"
Label12="Other Phone:"
Label13="Fax:"
Label14="Email Address:"
Label15="Alternate Email Address:"

Anda kemudian dapat mengonversi file sumber daya teks menjadi file biner bernama ApplicationResources.resources dengan menggunakan perintah berikut:

resgen ApplicationResources.txt

Contoh berikut kemudian menggunakan kelas ResourceReader untuk menghitung setiap sumber daya dalam file .resources biner mandiri dan untuk menampilkan nama kunci dan nilai yang sesuai.

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

public class Example1
{
   public static void Run()
   {
      Console.WriteLine("Resources in ApplicationResources.resources:");
      ResourceReader res = new ResourceReader(@".\ApplicationResources.resources");
      IDictionaryEnumerator dict = res.GetEnumerator();
      while (dict.MoveNext())
         Console.WriteLine($"   {dict.Key}: '{dict.Value}' (Type {dict.Value.GetType().Name})");
      res.Close();
   }
}
// The example displays the following output:
//       Resources in ApplicationResources.resources:
//          Label3: '"Last Name:"' (Type String)
//          Label2: '"Middle Name:"' (Type String)
//          Label1: '"First Name:"' (Type String)
//          Label7: '"State:"' (Type String)
//          Label6: '"City:"' (Type String)
//          Label5: '"Street Address:"' (Type String)
//          Label4: '"SSN:"' (Type String)
//          Label9: '"Home Phone:"' (Type String)
//          Label8: '"Zip Code:"' (Type String)
//          Title: '"Contact Information"' (Type String)
//          Label12: '"Other Phone:"' (Type String)
//          Label13: '"Fax:"' (Type String)
//          Label10: '"Business Phone:"' (Type String)
//          Label11: '"Mobile Phone:"' (Type String)
//          Label14: '"Email Address:"' (Type String)
//          Label15: '"Alternate Email Address:"' (Type String)
Imports System.Collections
Imports System.Resources

Module Example2
    Public Sub Main()
        Console.WriteLine("Resources in ApplicationResources.resources:")
        Dim res As New ResourceReader(".\ApplicationResources.resources")
        Dim dict As IDictionaryEnumerator = res.GetEnumerator()
        Do While dict.MoveNext()
            Console.WriteLine("   {0}: '{1}' (Type {2})", dict.Key, dict.Value, dict.Value.GetType().Name)
        Loop
        res.Close()
    End Sub
End Module
' The example displays output like the following:
'       Resources in ApplicationResources.resources:
'          Label3: '"Last Name:"' (Type String)
'          Label2: '"Middle Name:"' (Type String)
'          Label1: '"First Name:"' (Type String)
'          Label7: '"State:"' (Type String)
'          Label6: '"City:"' (Type String)
'          Label5: '"Street Address:"' (Type String)
'          Label4: '"SSN:"' (Type String)
'          Label9: '"Home Phone:"' (Type String)
'          Label8: '"Zip Code:"' (Type String)
'          Title: '"Contact Information"' (Type String)
'          Label12: '"Other Phone:"' (Type String)
'          Label13: '"Fax:"' (Type String)
'          Label10: '"Business Phone:"' (Type String)
'          Label11: '"Mobile Phone:"' (Type String)
'          Label14: '"Email Address:"' (Type String)
'          Label15: '"Alternate Email Address:"' (Type String)

Upaya untuk mengambil data sumber daya dari properti IDictionaryEnumerator.Value dapat melemparkan pengecualian berikut:

Biasanya, pengecualian ini dilemparkan jika file .resources telah dimodifikasi secara manual, jika rakitan di mana jenis didefinisikan belum disertakan dengan aplikasi atau telah dihapus secara tidak sengaja, atau jika rakitan adalah versi lama yang mendahului jenis. Jika salah satu pengecualian ini dilemparkan, Anda dapat mengambil sumber daya dengan menghitung setiap sumber daya dan memanggil metode GetResourceData, seperti yang ditunjukkan bagian berikut. Pendekatan ini memberi Anda beberapa informasi tentang jenis data yang coba dikembalikan oleh properti IDictionaryEnumerator.Value.

Mengambil sumber daya berdasarkan nama dengan GetResourceData

Pendekatan kedua untuk menghitung sumber daya dalam file .resources juga melibatkan navigasi melalui sumber daya dalam file dengan memanggil metode IDictionaryEnumerator.MoveNext. Untuk setiap sumber daya, Anda mengambil nama sumber daya dari properti IDictionaryEnumerator.Key, yang kemudian diteruskan ke metode GetResourceData(String, String, Byte[]) untuk mengambil data sumber daya. Ini dikembalikan sebagai array byte dalam argumen resourceData.

Pendekatan ini lebih rumit daripada mengambil nama dan nilai sumber daya dari properti IDictionaryEnumerator.Key dan IDictionaryEnumerator.Value, karena mengembalikan bita asli yang membentuk nilai sumber daya. Namun, jika upaya untuk mengambil sumber daya melemparkan pengecualian, metode GetResourceData dapat membantu mengidentifikasi sumber pengecualian dengan menyediakan informasi tentang jenis data sumber daya. Untuk informasi selengkapnya tentang string yang menunjukkan jenis data sumber daya, lihat GetResourceData.

Contoh berikut menggambarkan cara menggunakan pendekatan ini untuk mengambil sumber daya dan menangani pengecualian apa pun yang dilemparkan. Ini secara terprogram membuat file .resources biner yang berisi empat string, satu Boolean, satu bilangan bulat, dan satu bitmap. Untuk menjalankan contoh, lakukan hal berikut:

  1. Kompilasi dan jalankan kode sumber berikut, yang membuat file .resources bernama ContactResources.resources.

    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Resources;
    using System.Runtime.Versioning;
    
    public class Example5
    {
        [SupportedOSPlatform("windows")]
        public static void Run()
        {
            // Bitmap as stream.
            MemoryStream bitmapStream = new MemoryStream();
            Bitmap bmp = new Bitmap(@".\ContactsIcon.jpg");
            bmp.Save(bitmapStream, ImageFormat.Jpeg);
    
            // Define resources to be written.
            using (ResourceWriter rw = new ResourceWriter(@".\ContactResources.resources"))
            {
                rw.AddResource("Title", "Contact List");
                rw.AddResource("NColumns", 5);
                rw.AddResource("Icon", bitmapStream);
                rw.AddResource("Header1", "Name");
                rw.AddResource("Header2", "City");
                rw.AddResource("Header3", "State");
                rw.AddResource("ClientVersion", true);
                rw.Generate();
            }
        }
    }
    

    File kode sumber diberi nama CreateResources.cs. Anda dapat mengkompilasinya di C# dengan menggunakan perintah berikut:

    csc CreateResources.cs /r:library.dll
    
  2. Kompilasi dan jalankan kode berikut untuk menghitung sumber daya dalam file ContactResources.resources.

    using System;
    using System.Collections;
    using System.Drawing;
    using System.IO;
    using System.Resources;
    using System.Runtime.Versioning;
    
    public class Example6
    {
        [SupportedOSPlatform("windows")]
        public static void Run()
        {
            ResourceReader rdr = new ResourceReader(@".\ContactResources.resources");
            IDictionaryEnumerator dict = rdr.GetEnumerator();
            while (dict.MoveNext())
            {
                Console.WriteLine($"Resource Name: {dict.Key}");
                try
                {
                    Console.WriteLine($"   Value: {dict.Value}");
                }
                catch (FileNotFoundException)
                {
                    Console.WriteLine("   Exception: A file cannot be found.");
                    DisplayResourceInfo(rdr, (string)dict.Key, false);
                }
                catch (FormatException)
                {
                    Console.WriteLine("   Exception: Corrupted data.");
                    DisplayResourceInfo(rdr, (string)dict.Key, true);
                }
                catch (TypeLoadException)
                {
                    Console.WriteLine("   Exception: Cannot load the data type.");
                    DisplayResourceInfo(rdr, (string)dict.Key, false);
                }
            }
        }
    
        [SupportedOSPlatform("windows")]
        private static void DisplayResourceInfo(ResourceReader rr,
                                        string key, bool loaded)
        {
            string dataType = null;
            byte[] data = null;
            rr.GetResourceData(key, out dataType, out data);
    
            // Display the data type.
            Console.WriteLine($"   Data Type: {dataType}");
            // Display the bytes that form the available data.      
            Console.Write("   Data: ");
            int lines = 0;
            foreach (var dataItem in data)
            {
                lines++;
                Console.Write("{0:X2} ", dataItem);
                if (lines % 25 == 0)
                    Console.Write("\n         ");
            }
            Console.WriteLine();
            // Try to recreate current state of data.
            // Do: Bitmap, DateTimeTZI
            switch (dataType)
            {
                // Handle internally serialized string data (ResourceTypeCode members).
                case "ResourceTypeCode.String":
                    BinaryReader reader = new BinaryReader(new MemoryStream(data));
                    string binData = reader.ReadString();
                    Console.WriteLine($"   Recreated Value: {binData}");
                    break;
                case "ResourceTypeCode.Int32":
                    Console.WriteLine($"   Recreated Value: {BitConverter.ToInt32(data, 0)}");
                    break;
                case "ResourceTypeCode.Boolean":
                    Console.WriteLine($"   Recreated Value: {BitConverter.ToBoolean(data, 0)}");
                    break;
                // .jpeg image stored as a stream.
                case "ResourceTypeCode.Stream":
                    const int OFFSET = 4;
                    int size = BitConverter.ToInt32(data, 0);
                    Bitmap value1 = new Bitmap(new MemoryStream(data, OFFSET, size));
                    Console.WriteLine($"   Recreated Value: {value1}");
                    break;
                default:
                    break;
            }
            Console.WriteLine();
        }
    }
    

    Setelah memodifikasi kode sumber (misalnya, dengan sengaja melemparkan FormatException di akhir blok try), Anda dapat menjalankan contoh untuk melihat bagaimana panggilan ke GetResourceData memungkinkan Anda mengambil atau membuat ulang beberapa informasi sumber daya.