Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Hinweis
Dieser Artikel bezieht sich auf .NET Framework. Informationen, die für .NET 5+ (einschließlich .NET Core) gelten, finden Sie unter Ressourcen in RESX-Dateien.
Da XML-Ressourcendateien (RESX)-Dateien aus klar definierten XML-Dateien bestehen müssen, einschließlich eines Headers, der einem bestimmten Schema gefolgt von Daten in Namen-Wert-Paaren folgen muss, stellen Sie möglicherweise fest, dass das Manuelle Erstellen dieser Dateien fehleranfällig ist. Alternativ können Sie RESX-Dateien programmgesteuert mithilfe von Typen und Membern in der .NET-Klassenbibliothek erstellen. Sie können auch die .NET-Klassenbibliothek verwenden, um Ressourcen abzurufen, die in RESX-Dateien gespeichert sind. In diesem Artikel wird erläutert, wie Sie die Typen und Member im System.Resources Namespace verwenden können, um mit RESX-Dateien zu arbeiten.
In diesem Artikel wird die Arbeit mit XML-Dateien (RESX) erläutert, die Ressourcen enthalten. Informationen zum Arbeiten mit binären Ressourcendateien, die in Assemblys eingebettet wurden, finden Sie unter ResourceManager.
Warnung
Es gibt auch Möglichkeiten, mit RESX-Dateien zu arbeiten, die nicht programmgesteuert sind. Wenn Sie einem Visual Studio-Projekt eine Ressourcendatei hinzufügen, stellt Visual Studio eine Schnittstelle zum Erstellen und Verwalten einer RESX-Datei bereit und konvertiert die RESX-Datei automatisch zur Kompilierungszeit in eine RESSOURCENdatei. Sie können auch einen Text-Editor verwenden, um eine RESX-Datei direkt zu bearbeiten. Um jedoch zu vermeiden, dass die Datei beschädigt wird, achten Sie darauf, keine binären Informationen zu ändern, die in der Datei gespeichert sind.
Erstellen einer RESX-Datei
Sie können die System.Resources.ResXResourceWriter Klasse verwenden, um eine RESX-Datei programmgesteuert zu erstellen, indem Sie die folgenden Schritte ausführen:
Instanziieren Sie ein ResXResourceWriter Objekt, indem Sie die ResXResourceWriter(String) Methode aufrufen und den Namen der RESX-Datei angeben. Der Dateiname muss die RESX-Erweiterung enthalten. Wenn Sie das ResXResourceWriter Objekt in einem
using
Block instanziieren, müssen Sie die ResXResourceWriter.Close Methode in Schritt 3 nicht explizit aufrufen.Rufen Sie die ResXResourceWriter.AddResource Methode für jede Ressource auf, die Sie der Datei hinzufügen möchten. Verwenden Sie die Überladungen dieser Methode, um Zeichenfolgen-, Objekt- und binäre Daten (Bytearray) hinzuzufügen. Wenn es sich bei der Ressource um ein Objekt handelt, muss sie serialisierbar sein.
Rufen Sie die ResXResourceWriter.Close Methode auf, um die Ressourcendatei zu generieren und alle Ressourcen freizugeben. Wenn das ResXResourceWriter Objekt innerhalb eines
using
Blocks erstellt wurde, werden Ressourcen in die RESX-Datei geschrieben, und die vom ResXResourceWriter Objekt verwendeten Ressourcen werden am Ende desusing
Blocks freigegeben.
Die resultierende RESX-Datei verfügt über den entsprechenden Header und ein data
Tag für jede Ressource, die von der ResXResourceWriter.AddResource Methode hinzugefügt wird.
Warnung
Verwenden Sie Ressourcendateien nicht, um Kennwörter, sicherheitsrelevante Informationen oder private Daten zu speichern.
Im folgenden Beispiel wird eine RESX-Datei namens CarResources.resx erstellt, die sechs Zeichenfolgen, ein Symbol und zwei anwendungsdefinierte Objekte (zwei Automobile
Objekte) speichert. Die Automobile
im Beispiel definierte und instanziierte Klasse wird mit dem SerializableAttribute Attribut markiert.
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
Sie können visual Studio auch zum Erstellen von RESX-Dateien verwenden. Zur Kompilierungszeit verwendet Visual Studio den Ressourcendatei-Generator (Resgen.exe), um die RESX-Datei in eine Binärressourcendatei (.resources) zu konvertieren, und bettet sie auch in eine Anwendungsassembly oder eine Satellitenassembly ein.
Sie können eine RESX-Datei nicht in eine ausführbare Laufzeitdatei einbetten oder in eine Satellitenassembly kompilieren. Sie müssen Ihre RESX-Datei mithilfe des Ressourcendatei-Generators (Resgen.exe) in eine Binärressource-Datei (.resources) konvertieren. Die resultierende .resources-Datei kann dann in eine Anwendungsassembly oder eine Satellitenassembly eingebettet werden. Weitere Informationen finden Sie unter Erstellen von Ressourcendateien.
Aufzählen von Ressourcen
In einigen Fällen möchten Sie möglicherweise alle Ressourcen anstelle einer bestimmten Ressource aus einer RESX-Datei abrufen. Dazu können Sie die System.Resources.ResXResourceReader Klasse verwenden, die einen Enumerator für alle Ressourcen in der RESX-Datei bereitstellt. Die System.Resources.ResXResourceReader Klasse implementiert IDictionaryEnumerator, die ein DictionaryEntry Objekt zurückgibt, das eine bestimmte Ressource für jede Iteration der Schleife darstellt. Die DictionaryEntry.Key Eigenschaft gibt den Schlüssel der Ressource zurück, und seine DictionaryEntry.Value Eigenschaft gibt den Wert der Ressource zurück.
Im folgenden Beispiel wird ein ResXResourceReader Objekt für die im vorherigen Beispiel erstellte Datei CarResources.resx erstellt und durch die Ressourcendatei iteriert. Es fügt die beiden Automobile
Objekte, die in der Ressourcendatei definiert sind, zu einem System.Collections.Generic.List<T> Objekt hinzu, und es werden fünf der sechs Zeichenfolgen zu einem SortedList Objekt hinzugefügt. Die Werte im SortedList Objekt werden in ein Parameterarray konvertiert, das zum Anzeigen von Spaltenüberschriften in der Konsole verwendet wird. Die Automobile
Eigenschaftswerte werden auch in der Konsole angezeigt.
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
Abrufen einer bestimmten Ressource
Zusätzlich zum Aufzählen der Elemente in einer RESX-Datei können Sie eine bestimmte Ressource mithilfe der System.Resources.ResXResourceSet Klasse abrufen. Die ResourceSet.GetString(String) Methode ruft den Wert einer benannten Zeichenfolgenressource ab. Die ResourceSet.GetObject(String) Methode ruft den Wert eines benannten Objekts oder einer Binärdaten ab. Die Methode gibt ein Objekt zurück, für das anschließend eine Umwandlung (in C#) oder Konvertierung (in Visual Basic) in ein Objekt des geeigneten Typs erfolgen muss.
Im folgenden Beispiel wird die Überschriftenzeichenfolge eines Formulars und dessen Symbol anhand des Ressourcennamens abgerufen. Außerdem werden die im vorherigen Beispiel verwendeten anwendungsdefinierte Automobile
Objekte abgerufen und in einem DataGridView Steuerelement angezeigt.
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
Konvertieren von RESX-Dateien in binär.resources-Dateien
Das Konvertieren von RESX-Dateien in eingebettete Binärressourcendateien (.resources) hat erhebliche Vorteile. Obwohl RESX-Dateien während der Anwendungsentwicklung leicht zu lesen und zu verwalten sind, sind sie selten in fertigen Anwendungen enthalten. Wenn sie mit einer Anwendung verteilt werden, sind sie getrennt von der ausführbaren Anwendung und den zugehörigen Bibliotheken als separate Dateien vorhanden. Im Gegensatz dazu sind RESSOURCEN-Dateien in die ausführbare Datei der Anwendung oder die zugehörigen Assemblys eingebettet. Außerdem wird beim Einsatz von RESX-Dateien zur Laufzeit bei lokalisierten Anwendungen der Entwickler für die Behandlung des Ressourcenfallbacks in die Pflicht genommen. Wenn demgegenüber eine Sammlung von Satellitenassemblys erstellt wurde, die eingebettete RESOURCES-Dateien enthalten, übernimmt die Common Language Runtime die Zuständigkeit für den Ressourcenfallbackvorgang.
Um eine RESX-Datei in eine RESSOURCENdatei zu konvertieren, verwenden Sie den Ressourcendateigenerator (resgen.exe), der die folgende grundlegende Syntax aufweist:
resgen.exe .resxFilename
Das Ergebnis ist eine binäre Ressourcendatei mit demselben Stammdateinamen wie die RESX-Datei und die Dateierweiterung ".resources". Diese Datei kann dann während der Kompilierungszeit in eine ausführbare Datei oder Bibliothek kompiliert werden. Wenn Sie den Visual Basic-Compiler verwenden, verwenden Sie die folgende Syntax, um eine RESSOURCEN-Datei in die ausführbare Datei einer Anwendung einzubetten:
vbc filename .vb -resource: .resourcesFilename
Wenn Sie C# verwenden, lautet die Syntax wie folgt:
csc filename .cs -resource: .resourcesFilename
Die RESSOURCEN-Datei kann auch mithilfe von Assembly Linker (al.exe) in eine Satellitenassembly eingebettet werden, die die folgende grundlegende Syntax aufweist:
al resourcesFilename -out: assemblyFilename