Bagikan melalui


Bekerja dengan file .resx secara terprogram

Nota

Artikel ini berlaku untuk .NET Framework. Untuk informasi yang berlaku untuk .NET 5+ (termasuk .NET Core), lihat Sumber daya dalam file .resx.

Karena file sumber daya XML (.resx) harus terdiri dari XML yang terdefinisi dengan baik, termasuk header yang harus mengikuti skema tertentu diikuti oleh data dalam pasangan nama/nilai, Anda mungkin menemukan bahwa membuat file ini secara manual rawan kesalahan. Sebagai alternatif, Anda dapat membuat file .resx secara terprogram dengan menggunakan jenis dan anggota di Pustaka Kelas .NET. Anda juga dapat menggunakan Pustaka Kelas .NET untuk mengambil sumber daya yang disimpan dalam file .resx. Artikel ini menjelaskan cara menggunakan jenis dan anggota di ruang nama System.Resources untuk bekerja dengan file .resx.

Artikel ini membahas bekerja dengan file XML (.resx) yang berisi sumber daya. Untuk informasi tentang bekerja dengan file sumber daya biner yang telah disematkan dalam rakitan, lihat ResourceManager.

Peringatan

Ada juga cara untuk bekerja dengan file .resx selain secara terprogram. Saat Anda menambahkan file sumber daya ke proyek Visual Studio , Visual Studio menyediakan antarmuka untuk membuat dan memelihara file .resx, dan secara otomatis mengonversi file .resx ke file .resources pada waktu kompilasi. Anda juga dapat menggunakan editor teks untuk memanipulasi file .resx secara langsung. Namun, untuk menghindari kerusakan file, berhati-hatilah untuk tidak memodifikasi informasi biner apa pun yang disimpan dalam file.

Membuat file .resx

Anda dapat menggunakan System.Resources.ResXResourceWriter kelas untuk membuat file .resx secara terprogram, dengan mengikuti langkah-langkah berikut:

  1. Buat instans ResXResourceWriter objek dengan memanggil ResXResourceWriter(String) metode dan memberikan nama file .resx. Nama file harus menyertakan ekstensi .resx. Jika Anda membuat instans objek ResXResourceWriter dalam blok using, Anda tidak perlu secara eksplisit memanggil metode ResXResourceWriter.Close di langkah 3.

  2. ResXResourceWriter.AddResource Panggil metode untuk setiap sumber daya yang ingin Anda tambahkan ke file. Gunakan kelebihan beban metode ini untuk menambahkan data string, objek, dan biner (byte array). Jika sumber daya adalah objek, sumber daya harus dapat diserialisasikan.

  3. ResXResourceWriter.Close Panggil metode untuk menghasilkan file sumber daya dan untuk merilis semua sumber daya. Jika objek ResXResourceWriter dibuat dalam blok using, sumber daya dituliskan ke berkas .resx dan sumber daya yang digunakan oleh objek ResXResourceWriter dilepaskan di akhir blok using.

File .resx yang dihasilkan memiliki header yang sesuai dan tag data untuk setiap sumber daya yang ditambahkan oleh metode ResXResourceWriter.AddResource.

Peringatan

Jangan gunakan file sumber daya untuk menyimpan kata sandi, informasi yang sensitif keamanan, atau data privat.

Contoh berikut membuat file .resx bernama CarResources.resx yang menyimpan enam string, ikon, dan dua objek yang ditentukan aplikasi (dua Automobile objek). Kelas Automobile , yang didefinisikan dan dibuat dalam contoh, ditandai dengan SerializableAttribute atribut .

using System;
using System.Drawing;
using System.Resources;

[Serializable()] public class Automobile
{
   private string carMake;
   private string carModel;
   private int carYear;
   private int carDoors;
   private int carCylinders;

   public Automobile(string make, string model, int year) :
                     this(make, model, year, 0, 0)
   { }

   public Automobile(string make, string model, int year,
                     int doors, int cylinders)
   {
      this.carMake = make;
      this.carModel = model;
      this.carYear = year;
      this.carDoors = doors;
      this.carCylinders = cylinders;
   }

   public string Make {
      get { return this.carMake; }
   }

   public string Model {
      get {return this.carModel; }
   }

   public int Year {
      get { return this.carYear; }
   }

   public int Doors {
      get { return this.carDoors; }
   }

   public int Cylinders {
      get { return this.carCylinders; }
   }
}

public class Example
{
   public static void Main()
   {
      // Instantiate an Automobile object.
      Automobile car1 = new Automobile("Ford", "Model N", 1906, 0, 4);
      Automobile car2 = new Automobile("Ford", "Model T", 1909, 2, 4);
      // Define a resource file named CarResources.resx.
      using (ResXResourceWriter resx = new ResXResourceWriter(@".\CarResources.resx"))
      {
         resx.AddResource("Title", "Classic American Cars");
         resx.AddResource("HeaderString1", "Make");
         resx.AddResource("HeaderString2", "Model");
         resx.AddResource("HeaderString3", "Year");
         resx.AddResource("HeaderString4", "Doors");
         resx.AddResource("HeaderString5", "Cylinders");
         resx.AddResource("Information", SystemIcons.Information);
         resx.AddResource("EarlyAuto1", car1);
         resx.AddResource("EarlyAuto2", car2);
      }
   }
}
Imports System.Drawing
Imports System.Resources

<Serializable()> Public Class Automobile
    Private carMake As String
    Private carModel As String
    Private carYear As Integer
    Private carDoors AS Integer
    Private carCylinders As Integer

    Public Sub New(make As String, model As String, year As Integer)
        Me.New(make, model, year, 0, 0)
    End Sub

    Public Sub New(make As String, model As String, year As Integer,
                   doors As Integer, cylinders As Integer)
        Me.carMake = make
        Me.carModel = model
        Me.carYear = year
        Me.carDoors = doors
        Me.carCylinders = cylinders
    End Sub

    Public ReadOnly Property Make As String
        Get
            Return Me.carMake
        End Get
    End Property

    Public ReadOnly Property Model As String
        Get
            Return Me.carModel
        End Get
    End Property

    Public ReadOnly Property Year As Integer
        Get
            Return Me.carYear
        End Get
    End Property

    Public ReadOnly Property Doors As Integer
        Get
            Return Me.carDoors
        End Get
    End Property

    Public ReadOnly Property Cylinders As Integer
        Get
            Return Me.carCylinders
        End Get
    End Property
End Class

Module Example
    Public Sub Main()
        ' Instantiate an Automobile object.
        Dim car1 As New Automobile("Ford", "Model N", 1906, 0, 4)
        Dim car2 As New Automobile("Ford", "Model T", 1909, 2, 4)
        ' Define a resource file named CarResources.resx.
        Using resx As New ResXResourceWriter(".\CarResources.resx")
            resx.AddResource("Title", "Classic American Cars")
            resx.AddResource("HeaderString1", "Make")
            resx.AddResource("HeaderString2", "Model")
            resx.AddResource("HeaderString3", "Year")
            resx.AddResource("HeaderString4", "Doors")
            resx.AddResource("HeaderString5", "Cylinders")
            resx.AddResource("Information", SystemIcons.Information)
            resx.AddResource("EarlyAuto1", car1)
            resx.AddResource("EarlyAuto2", car2)
        End Using
    End Sub
End Module

Petunjuk / Saran

Anda juga dapat menggunakan Visual Studio untuk membuat file .resx. Pada waktu kompilasi, Visual Studio menggunakan Resource File Generator (Resgen.exe) untuk mengonversi file .resx ke file sumber daya biner (.resources), dan juga menyematkannya di rakitan aplikasi atau rakitan satelit.

Anda tidak dapat menyematkan file .resx dalam eksekusi runtime atau mengompilasinya ke dalam rakitan satelit. Anda harus mengonversi file .resx Anda menjadi file sumber daya biner (.resources) dengan menggunakan Resource File Generator (Resgen.exe). File .resources yang dihasilkan kemudian dapat disematkan dalam rakitan aplikasi atau rakitan satelit. Untuk informasi selengkapnya, lihat Membuat file sumber daya.

Menghitung sumber daya

Dalam beberapa kasus, Anda mungkin ingin mengambil semua sumber daya, bukan sumber daya tertentu, dari file .resx. Untuk melakukan ini, Anda dapat menggunakan System.Resources.ResXResourceReader kelas , yang menyediakan enumerator untuk semua sumber daya dalam file .resx. Kelas System.Resources.ResXResourceReader mengimplementasikan IDictionaryEnumerator, yang mengembalikan DictionaryEntry objek yang mewakili sumber daya tertentu untuk setiap iterasi perulangan. Propertinya DictionaryEntry.Key mengembalikan kunci sumber daya, dan propertinya DictionaryEntry.Value mengembalikan nilai sumber daya.

Contoh berikut membuat ResXResourceReader objek untuk file CarResources.resx yang dibuat dalam contoh sebelumnya dan melakukan iterasi melalui file sumber daya. Ini menambahkan dua Automobile objek yang ditentukan dalam file sumber daya ke System.Collections.Generic.List<T> objek, dan menambahkan lima dari enam string ke SortedList objek. Nilai-nilai dalam objek SortedList dikonversi menjadi array parameter, yang digunakan untuk menampilkan judul kolom ke konsol. Nilai Automobile properti juga ditampilkan pada konsol.

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

public class Example
{
   public static void Main()
   {
      string resxFile = @".\CarResources.resx";
      List<Automobile> autos = new List<Automobile>();
      SortedList headers = new SortedList();

      using (ResXResourceReader resxReader = new ResXResourceReader(resxFile))
      {
         foreach (DictionaryEntry entry in resxReader) {
            if (((string) entry.Key).StartsWith("EarlyAuto"))
               autos.Add((Automobile) entry.Value);
            else if (((string) entry.Key).StartsWith("Header"))
               headers.Add((string) entry.Key, (string) entry.Value);
         }
      }
      string[] headerColumns = new string[headers.Count];
      headers.GetValueList().CopyTo(headerColumns, 0);
      Console.WriteLine("{0,-8} {1,-10} {2,-4}   {3,-5}   {4,-9}\n",
                        headerColumns);
      foreach (var auto in autos)
         Console.WriteLine("{0,-8} {1,-10} {2,4}   {3,5}   {4,9}",
                           auto.Make, auto.Model, auto.Year,
                           auto.Doors, auto.Cylinders);
   }
}
// The example displays the following output:
//       Make     Model      Year   Doors   Cylinders
//
//       Ford     Model N    1906       0           4
//       Ford     Model T    1909       2           4
Imports System.Collections
Imports System.Collections.Generic
Imports System.Resources

Module Example
    Public Sub Main()
        Dim resxFile As String = ".\CarResources.resx"
        Dim autos As New List(Of Automobile)
        Dim headers As New SortedList()

        Using resxReader As New ResXResourceReader(resxFile)
            For Each entry As DictionaryEntry In resxReader
                If CType(entry.Key, String).StartsWith("EarlyAuto") Then
                    autos.Add(CType(entry.Value, Automobile))
                Else If CType(entry.Key, String).StartsWith("Header") Then
                    headers.Add(CType(entry.Key, String), CType(entry.Value, String))
                End If
            Next
        End Using
        Dim headerColumns(headers.Count - 1) As String
        headers.GetValueList().CopyTo(headerColumns, 0)
        Console.WriteLine("{0,-8} {1,-10} {2,-4}   {3,-5}   {4,-9}",
                          headerColumns)
        Console.WriteLine()
        For Each auto In autos
            Console.WriteLine("{0,-8} {1,-10} {2,4}   {3,5}   {4,9}",
                              auto.Make, auto.Model, auto.Year,
                              auto.Doors, auto.Cylinders)
        Next
    End Sub
End Module
' The example displays the following output:
'       Make     Model      Year   Doors   Cylinders
'       
'       Ford     Model N    1906       0           4
'       Ford     Model T    1909       2           4

Mengambil sumber daya tertentu

Selain menghitung item dalam file .resx, Anda dapat mengambil sumber daya tertentu berdasarkan nama dengan menggunakan System.Resources.ResXResourceSet kelas . Metode ResourceSet.GetString(String) mengambil nilai dari sumber daya bertipe string yang ditentukan. Metode ini ResourceSet.GetObject(String) mengambil kembali nilai dari objek yang bernama atau data biner. Metode mengembalikan objek yang kemudian harus di-casting (dalam C#) atau dikonversi (di Visual Basic) ke objek dengan tipe yang sesuai.

Contoh berikut mengambil teks judul dan ikon formulir berdasarkan nama sumber daya mereka. Ini juga mengambil objek yang didefinisikan oleh aplikasi yang digunakan dalam contoh sebelumnya dan menampilkannya dalam kontrol Automobile.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Resources;
using System.Windows.Forms;

public class CarDisplayApp : Form
{
   private const string resxFile = @".\CarResources.resx";
   Automobile[] cars;

   public static void Main()
   {
      CarDisplayApp app = new CarDisplayApp();
      Application.Run(app);
   }

   public CarDisplayApp()
   {
      // Instantiate controls.
      PictureBox pictureBox = new PictureBox();
      pictureBox.Location = new Point(10, 10);
      this.Controls.Add(pictureBox);
      DataGridView grid = new DataGridView();
      grid.Location = new Point(10, 60);
      this.Controls.Add(grid);

      // Get resources from .resx file.
      using (ResXResourceSet resxSet = new ResXResourceSet(resxFile))
      {
         // Retrieve the string resource for the title.
         this.Text = resxSet.GetString("Title");
         // Retrieve the image.
         Icon image = (Icon) resxSet.GetObject("Information", true);
         if (image != null)
            pictureBox.Image = image.ToBitmap();

         // Retrieve Automobile objects.
         List<Automobile> carList = new List<Automobile>();
         string resName = "EarlyAuto";
         Automobile auto;
         int ctr = 1;
         do {
            auto = (Automobile) resxSet.GetObject(resName + ctr.ToString());
            ctr++;
            if (auto != null)
               carList.Add(auto);
         } while (auto != null);
         cars = carList.ToArray();
         grid.DataSource = cars;
      }
   }
}
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Resources
Imports System.Windows.Forms

Public Class CarDisplayApp : Inherits Form
    Private Const resxFile As String = ".\CarResources.resx"
    Dim cars() As Automobile

    Public Shared Sub Main()
        Dim app As New CarDisplayApp()
        Application.Run(app)
    End Sub

    Public Sub New()
        ' Instantiate controls.
        Dim pictureBox As New PictureBox()
        pictureBox.Location = New Point(10, 10)
        Me.Controls.Add(pictureBox)
        Dim grid As New DataGridView()
        grid.Location = New Point(10, 60)
        Me.Controls.Add(grid)

        ' Get resources from .resx file.
        Using resxSet As New ResXResourceSet(resxFile)
            ' Retrieve the string resource for the title.
            Me.Text = resxSet.GetString("Title")
            ' Retrieve the image.
            Dim image As Icon = CType(resxSet.GetObject("Information", True), Icon)
            If image IsNot Nothing Then
                pictureBox.Image = image.ToBitmap()
            End If

            ' Retrieve Automobile objects.  
            Dim carList As New List(Of Automobile)
            Dim resName As String = "EarlyAuto"
            Dim auto As Automobile
            Dim ctr As Integer = 1
            Do
                auto = CType(resxSet.GetObject(resName + ctr.ToString()), Automobile)
                ctr += 1
                If auto IsNot Nothing Then carList.Add(auto)
            Loop While auto IsNot Nothing
            cars = carList.ToArray()
            grid.DataSource = cars
        End Using
    End Sub
End Class

Mengonversi file .resx ke file .resources biner

Mengonversi file .resx menjadi file sumber daya biner (.resources) yang disematkan memiliki keuntungan signifikan. Meskipun file .resx mudah dibaca dan dikelola selama pengembangan aplikasi, file tersebut jarang disertakan dengan aplikasi yang sudah selesai. Jika didistribusikan dengan aplikasi, mereka ada sebagai file terpisah selain dari aplikasi yang dapat dieksekusi dan pustaka yang menyertainya. Sebaliknya, file .resources disematkan dalam aplikasi yang dapat dieksekusi atau rakitan yang menyertainya. Selain itu, untuk aplikasi yang dilokalkan, mengandalkan file .resx pada runtime menempatkan tanggung jawab untuk menangani fallback sumber daya pada pengembang. Sebaliknya, jika sekumpulan ansambel satelit yang berisi file bersifat .resources yang disematkan telah dibuat, runtime bahasa umum .NET menangani proses fallback sumber daya.

Untuk mengonversi file .resx ke file .resources , Anda menggunakan Resource File Generator (resgen.exe), yang memiliki sintaks dasar berikut:

 resgen.exe .resxFilename

Hasilnya adalah file sumber daya biner yang memiliki nama file akar yang sama dengan file .resx dan ekstensi file .resources. File ini kemudian dapat dikompilasi ke dalam executable atau pustaka pada waktu kompilasi. Jika Anda menggunakan pengkompilasi Visual Basic, gunakan sintaks berikut untuk menyematkan file .resources dalam aplikasi yang dapat dieksekusi:

vbc filename .vb -resource: .resourcesFilename

Jika Anda menggunakan C#, sintaksnya adalah sebagai berikut:

 csc filename .cs -resource: .resourcesFilename

File .resources juga dapat disematkan dalam rakitan satelit dengan menggunakan Assembly Linker (al.exe), yang memiliki sintaks dasar berikut:

al resourcesFilename -out: assemblyFilename

Lihat juga