A .resx-fájlok programozott működése
Feljegyzés
Ez a cikk a .NET-keretrendszer vonatkozik. A .NET 5+ verzióra (beleértve a .NET Core-t is) vonatkozó információkért tekintse meg a .resx fájlok erőforrásait.
Mivel az XML-erőforrásfájloknak (.resx) jól definiált XML-fájlokból kell állniuk, beleértve egy fejlécet is, amelynek egy adott sémát kell követnie, majd a név-érték párokban szereplő adatokat, előfordulhat, hogy a fájlok manuális létrehozása hibalehetőséget jelent. Alternatív megoldásként programozott módon is létrehozhat .resx fájlokat a .NET osztálytár típusok és tagok használatával. A .NET-osztálytár használatával is lekérheti a .resx fájlokban tárolt erőforrásokat. Ez a cikk bemutatja, hogyan használhatja a névtérben lévő típusokat és tagokat a System.Resources .resx fájlok használatához.
Ez a cikk az erőforrásokat tartalmazó XML-fájlok (.resx) használatát ismerteti. A szerelvényekbe beágyazott bináris erőforrásfájlok használatával kapcsolatos információkért lásd: ResourceManager.
Figyelmeztetés
A .resx-fájlokat programozott módon kívül más módon is kezelheti. Amikor erőforrásfájlt ad hozzá egy Visual Studio-projekthez , a Visual Studio felületet biztosít egy .resx-fájl létrehozásához és karbantartásához, és fordításkor automatikusan .resources fájllá alakítja a .resx fájlt. A .resx fájlokat közvetlenül szövegszerkesztővel is módosíthatja. A fájl sérülésének elkerülése érdekében azonban ügyeljen arra, hogy ne módosítsa a fájlban tárolt bináris adatokat.
.resx fájl létrehozása
Az System.Resources.ResXResourceWriter osztály segítségével programozott módon hozhat létre .resx fájlt az alábbi lépések végrehajtásával:
Példányosíthat egy ResXResourceWriter objektumot a ResXResourceWriter(String) metódus meghívásával és a .resx fájl nevének megadásával. A fájlnévnek tartalmaznia kell a .resx kiterjesztést. Ha egy
using
blokkban példányosít ResXResourceWriter egy objektumot, nem kell explicit módon meghívnia a metódust a ResXResourceWriter.Close 3. lépésben.Hívja meg a ResXResourceWriter.AddResource fájlhoz hozzáadni kívánt összes erőforrás metódusát. A metódus túlterhelésével sztring-, objektum- és bináris (bájttömb) adatokat adhat hozzá. Ha az erőforrás objektum, akkor szerializálhatónak kell lennie.
ResXResourceWriter.Close Az erőforrásfájl létrehozásához és az összes erőforrás kiadásához hívja meg a metódust. Ha az ResXResourceWriter objektum egy
using
blokkon belül jött létre, a rendszer az erőforrásokat a .resx fájlba írja, és az ResXResourceWriter objektum által használt erőforrások a blokk végénusing
lesznek felszabadítva.
Az eredményként kapott .resx fájl rendelkezik a megfelelő fejléccel és címkével data
a ResXResourceWriter.AddResource metódus által hozzáadott egyes erőforrásokhoz.
Figyelmeztetés
Ne használjon erőforrásfájlokat jelszavak, biztonsági bizalmas adatok vagy személyes adatok tárolására.
Az alábbi példa egy CarResources.resx nevű .resx fájlt hoz létre, amely hat sztringet, egy ikont és két alkalmazás által definiált objektumot (két Automobile
objektumot) tárol. A Automobile
példában definiált és példányosított osztály az attribútummal SerializableAttribute van megjelölve.
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
Tipp.
A Visual Studióval .resx fájlokat is létrehozhat. Fordításkor a Visual Studio az erőforrásfájl-generátorral (Resgen.exe) bináris erőforrásfájllá (.resources) konvertálja a .resx fájlt, és beágyazza egy alkalmazásszerelvénybe vagy egy műholdas szerelvénybe is.
A .resx fájlokat nem ágyazhatja be futtatókörnyezetbe, és nem fordíthatja azt műholdas szerelvénybe. A .resx fájlt bináris erőforrásfájllá (.resources) kell konvertálnia az erőforrásfájl-generátor (Resgen.exe) használatával. Az eredményül kapott .resources fájl ezután beágyazható egy alkalmazásszerelvénybe vagy egy műholdas szerelvénybe. További információ: Erőforrásfájlok létrehozása.
Erőforrások számbavétele
Bizonyos esetekben előfordulhat, hogy az összes erőforrást egy .resx fájlból szeretné lekérni egy adott erőforrás helyett. Ehhez használhatja az System.Resources.ResXResourceReader osztályt, amely enumerátort biztosít a .resx fájl összes erőforrásához. Az System.Resources.ResXResourceReader osztály implementál IDictionaryEnumeratoregy DictionaryEntry objektumot, amely egy adott erőforrást jelöl a ciklus egyes iterációihoz. A DictionaryEntry.Key tulajdonság visszaadja az erőforrás kulcsát, a tulajdonsága DictionaryEntry.Value pedig az erőforrás értékét.
Az alábbi példa létrehoz egy ResXResourceReader objektumot az előző példában létrehozott CarResources.resx fájlhoz, és iterálja az erőforrásfájlt. Hozzáadja az erőforrásfájlban definiált két Automobile
objektumot egy System.Collections.Generic.List<T> objektumhoz, és a hat sztringből ötöt hozzáad egy SortedList objektumhoz. Az objektum értékei SortedList paramétertömbré alakulnak, amely a konzolon lévő oszlopfejlécek megjelenítésére szolgál. A Automobile
tulajdonságértékek a konzolon is megjelennek.
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
Adott erőforrás lekérése
A .resx fájl elemeinek számbavétele mellett az osztály használatával név szerint is lekérhet egy adott erőforrást System.Resources.ResXResourceSet . A ResourceSet.GetString(String) metódus lekéri egy elnevezett sztringerőforrás értékét. A ResourceSet.GetObject(String) metódus lekéri egy elnevezett objektum vagy bináris adat értékét. A metódus egy olyan objektumot ad vissza, amelyet ezután el kell vetíteni (C#-ban) vagy konvertálni (a Visual Basicben) egy megfelelő típusú objektummá.
Az alábbi példa lekéri egy űrlap képaláírás sztringjét és ikonját az erőforrásnevük alapján. Emellett lekéri az előző példában használt alkalmazás által definiált Automobile
objektumokat, és megjeleníti őket egy DataGridView vezérlőben.
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
.resx fájlok konvertálása bináris .resources fájlokká
A .resx fájlok konvertálása beágyazott bináris erőforrásfájlokká (.resources) jelentős előnyökkel jár. Bár a .resx fájlok könnyen olvashatók és karbantarthatóak az alkalmazásfejlesztés során, ritkán szerepelnek a kész alkalmazásokban. Ha egy alkalmazással vannak elosztva, az alkalmazás végrehajtható fájljaitól és a hozzá tartozó kódtáraktól eltekintve különálló fájlokként léteznek. Ezzel szemben a .resources fájlok az alkalmazás végrehajtható vagy a hozzá tartozó szerelvényekbe vannak beágyazva. Emellett a honosított alkalmazások esetében a .resx fájlok futásidőben történő támaszkodása a fejlesztőre bízza az erőforrás-tartalék kezelésének felelősségét. Ezzel szemben, ha beágyazott .resources fájlokat tartalmazó műholdas szerelvényeket hoztak létre, a közös nyelvi futtatókörnyezet kezeli az erőforrás-tartalék folyamatot.
A .resx fájl .resources fájllá alakításához az erőforrásfájl-generátort (resgen.exe) kell használnia, amely az alábbi alapszintaxissal rendelkezik:
resgen.exe .resxFilename
Az eredmény egy bináris erőforrásfájl, amelynek gyökérfájlneve megegyezik a .resx fájl és a .resources fájlkiterjesztés nevével. Ez a fájl ezután lefordítható végrehajtható vagy tárba fordításkor. Ha a Visual Basic fordítót használja, az alábbi szintaxissal ágyazhat be egy .resources-fájlt egy alkalmazás végrehajtható fájljában:
vbc filename .vb -resource: .resourcesFilename
Ha C#-ot használ, a szintaxis a következő:
csc filename .cs -resource: .resourcesFilename
A .resources fájl a Assembly Linker (al.exe) használatával is beágyazható egy műholdas szerelvénybe, amely az alábbi alapvető szintaxissal rendelkezik:
al resourcesFilename -out: assemblyFilename