Abrufen von Ressourcen in .NET-Apps

Bei der Arbeit mit lokalisierten Ressourcen in .NET-Apps sollten Sie idealerweise die Ressourcen für die Standardkultur bzw. neutrale Kultur mit der Hauptassembly packen und eine separate Satellitenassembly für jede Sprache oder Kultur erstellen, die Ihre App unterstützt. Anschließend können Sie die ResourceManager -Klasse wie im nächsten Abschnitt beschrieben für den Zugriff auf benannte Ressourcen verwenden. Wenn Sie die Ressourcen nicht in die Hauptassembly und Satellitenassemblys einbetten möchten, können Sie auch direkt auf binäre RESOURCES-Dateien zugreifen, wie im Abschnitt Abrufen von Ressourcen aus Ressourcendateien weiter unten in diesem Artikel erläutert.

Abrufen von Ressourcen aus Assemblys

Die ResourceManager Klasse ermöglicht den Zugriff auf Ressourcen zur Laufzeit. Verwenden Sie die ResourceManager.GetString -Methode, um Zeichenfolgenressourcen abzurufen und die ResourceManager.GetObject - oder ResourceManager.GetStream - Methode, um Nicht-Zeichenfolgenressourcen abzurufen. Jede Methode enthält zwei Überladungen:

  • Eine Überladung, deren einzelner Parameter eine Zeichenfolge ist, der den Namen der Ressource enthält. Die Methode versucht, die Ressource für die aktuelle Kultur abzurufen. Weitere Informationen finden Sie in den Methoden GetString(String), GetObject(String)und GetStream(String) .

  • Eine Überladung, die über zwei Parameter verfügt: eine Zeichenfolge mit dem Namen der Ressource und ein CultureInfo -Objekt, das die Kultur darstellt, deren Ressourcen abgerufen werden. Wenn keine Ressource für diese Kultur gefunden werden kann, verwendet der Ressourcen-Manager Fallback-Regeln, um eine entsprechende Ressource abzurufen. Weitere Informationen finden Sie in den Methoden GetString(String, CultureInfo), GetObject(String, CultureInfo)und GetStream(String, CultureInfo) .

Der Ressourcen-Manager verwendet den Ressourcenfallback-Prozess um zu steuern, wie die Anwendung kulturabhängige Ressourcen abruft. Weitere Informationen finden Sie im Abschnitt „Ressourcenfallbackprozess“ unter Packen und Bereitstellen von Ressourcen. Informationen zum Instanziieren eines ResourceManager -Objekts finden Sie im Abschnitt „Instanziieren eines ResourceManager-Objekts“ in der ResourceManager -Themenklasse.

Beispiel für das Abrufen von Zeichenfolgendaten

Im folgenden Beispiel wird die GetString(String) -Methode aufgerufen, um die Zeichenfolgenressourcen für die aktuelle UI-Kultur abzurufen. Es umfasst eine neutrale Zeichenfolgenressource für die Kultur Englisch (USA) und lokalisierte Ressourcen für die Kulturen Französisch (Frankreich) und Russisch (Russische Föderation). Die folgende Ressource für Englisch (USA) ist in einer Strings.txt-Datei enthalten:

TimeHeader=The current time is

Die Ressource für Französisch (Frankreich) befindet sich in einer Datei namens Strings.fr-FR.txt:

TimeHeader=L'heure actuelle est

Die Ressource für Russisch (Russische Föderation) befindet sich in einer Datei namens Strings.ru-RU.txt:

TimeHeader=Текущее время —

Der Quellcode für dieses Beispiel (in einer Datei namens GetString.cs für die C#-Version des Codes und GetString.vb für die Visual Basic-Version) definiert ein Zeichenfolgenarray, das die Namen von vier Kulturen enthält: die drei Kulturen, für die Ressourcen verfügbar sind und die Kultur Spanisch (Spanien). Eine Schleife, die nach dem Zufallsprinzip fünf Mal ausgeführt wird, wählt eine dieser Kulturen und weist sie den Thread.CurrentCulture - und CultureInfo.CurrentUICulture -Eigenschaften. Sie ruft dann die GetString(String) -Methode auf, um die lokalisierte Zeichenfolge abzurufen, die zusammen mit der Uhrzeit angezeigt wird.

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguageAttribute("en-US")]

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "ru-RU", "es-ES" };
      Random rnd = new Random();
      ResourceManager rm = new ResourceManager("Strings",
                               typeof(Example).Assembly);

      for (int ctr = 0; ctr <= cultureNames.Length; ctr++) {
         string cultureName = cultureNames[rnd.Next(0, cultureNames.Length)];
         CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
         Thread.CurrentThread.CurrentCulture = culture;
         Thread.CurrentThread.CurrentUICulture = culture;

         Console.WriteLine("Current culture: {0}", culture.NativeName);
         string timeString = rm.GetString("TimeHeader");
         Console.WriteLine("{0} {1:T}\n", timeString, DateTime.Now);
      }
   }
}
// The example displays output like the following:
//    Current culture: English (United States)
//    The current time is 9:34:18 AM
//
//    Current culture: Español (España, alfabetización internacional)
//    The current time is 9:34:18
//
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18
//
//    Current culture: français (France)
//    L'heure actuelle est 09:34:18
//
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly: NeutralResourcesLanguageAttribute("en-US")>

Module Example
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "fr-FR", "ru-RU", "es-ES"}
        Dim rnd As New Random()
        Dim rm As New ResourceManager("Strings", GetType(Example).Assembly)

        For ctr As Integer = 0 To cultureNames.Length
            Dim cultureName As String = cultureNames(rnd.Next(0, cultureNames.Length))
            Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureName)
            Thread.CurrentThread.CurrentCulture = culture
            Thread.CurrentThread.CurrentUICulture = culture

            Console.WriteLine("Current culture: {0}", culture.NativeName)
            Dim timeString As String = rm.GetString("TimeHeader")
            Console.WriteLine("{0} {1:T}", timeString, Date.Now)
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays output similar to the following:
'    Current culture: English (United States)
'    The current time is 9:34:18 AM
'    
'    Current culture: Español (España, alfabetización internacional)
'    The current time is 9:34:18
'    
'    Current culture: русский (Россия)
'    Текущее время — 9:34:18
'    
'    Current culture: français (France)
'    L'heure actuelle est 09:34:18
'    
'    Current culture: русский (Россия)
'    Текущее время — 9:34:18

Die folgende Batchdatei (BAT-Datei) kompiliert das Beispiel und generiert Satellitenassemblys in den entsprechenden Verzeichnissen. Die Befehle werden für die C#-Sprache und Compiler bereitgestellt. Ändern Sie in Visual Basic csc in vbcund ändern Sie GetString.cs in GetString.vb.

resgen strings.txt
csc GetString.cs -resource:strings.resources

resgen strings.fr-FR.txt
md fr-FR
al -embed:strings.fr-FR.resources -culture:fr-FR -out:fr-FR\GetString.resources.dll

resgen strings.ru-RU.txt
md ru-RU
al -embed:strings.ru-RU.resources -culture:ru-RU -out:ru-RU\GetString.resources.dll

Wenn die aktuelle UI-Kultur Spanisch (Spanien) ist, beachten Sie, dass im Beispiel englische Ressourcen angezeigt werden, da Spanisch-Ressourcen nicht verfügbar sind und Englisch die Standardkultur des Beispiels ist.

Beispiele für das Abrufen von Objektdaten

Sie können die GetObject - und GetStream -Methoden zum Abrufen von Objektdaten verwenden. Dies schließt primitive Datentypen, serialisierbare Objekte und Objekte ein, die im Binärformat (z.B. Bilder) gespeichert sind.

Im folgenden Beispiel wird die GetStream(String) -Methode verwendet, um eine Bitmap abzurufen, die im Begrüßungsbildschirm-Fenster einer App erscheint. Der folgende Quellcode in einer Datei mit dem Namen CreateResources.cs (für C#) oder CreateResources.vb (für Visual Basic) generiert eine .resx-Datei, die das serialisierte Bild enthält. In diesem Fall wird das Bild aus einer Datei namens SplashScreen.jpg geladen. Sie können den Dateinamen ändern und damit Ihr eigenes Bild laden.

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Resources;

public class Example
{
   public static void Main()
   {
      Bitmap bmp = new Bitmap(@".\SplashScreen.jpg");
      MemoryStream imageStream = new MemoryStream();
      bmp.Save(imageStream, ImageFormat.Jpeg);

      ResXResourceWriter writer = new ResXResourceWriter("AppResources.resx");
      writer.AddResource("SplashScreen", imageStream);
      writer.Generate();
      writer.Close();
   }
}
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Resources

Module Example
    Public Sub Main()
        Dim bmp As New Bitmap(".\SplashScreen.jpg")
        Dim imageStream As New MemoryStream()
        bmp.Save(imageStream, ImageFormat.Jpeg)

        Dim writer As New ResXResourceWriter("AppResources.resx")
        writer.AddResource("SplashScreen", imageStream)
        writer.Generate()
        writer.Close()
    End Sub
End Module

Der folgende Code ruft die Ressource ab und zeigt das Bild in einem PictureBox -Steuerelement.

using System;
using System.Drawing;
using System.IO;
using System.Resources;
using System.Windows.Forms;

public class Example
{
   public static void Main()
   {
      ResourceManager rm = new ResourceManager("AppResources", typeof(Example).Assembly);
      Bitmap screen = (Bitmap) Image.FromStream(rm.GetStream("SplashScreen"));

      Form frm = new Form();
      frm.Size = new Size(300, 300);

      PictureBox pic = new PictureBox();
      pic.Bounds = frm.RestoreBounds;
      pic.BorderStyle = BorderStyle.Fixed3D;
      pic.Image = screen;
      pic.SizeMode = PictureBoxSizeMode.StretchImage;

      frm.Controls.Add(pic);
      pic.Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
                   AnchorStyles.Left | AnchorStyles.Right;

      frm.ShowDialog();
   }
}
Imports System.Drawing
Imports System.IO
Imports System.Resources
Imports System.Windows.Forms

Module Example
    Public Sub Main()
        Dim rm As New ResourceManager("AppResources", GetType(Example).Assembly)
        Dim screen As Bitmap = CType(Image.FromStream(rm.GetStream("SplashScreen")), Bitmap)

        Dim frm As New Form()
        frm.Size = new Size(300, 300)

        Dim pic As New PictureBox()
        pic.Bounds = frm.RestoreBounds
        pic.BorderStyle = BorderStyle.Fixed3D
        pic.Image = screen
        pic.SizeMode = PictureBoxSizeMode.StretchImage

        frm.Controls.Add(pic)
        pic.Anchor = AnchorStyles.Top Or AnchorStyles.Bottom Or
                     AnchorStyles.Left Or AnchorStyles.Right

        frm.ShowDialog()
    End Sub
End Module

Sie können die folgende Batchdatei verwenden, um das C#-Beispiel zu erstellen. Ändern Sie in Visual Basic csc in vbcund ändern Sie die Erweiterung des Quellcodes von .cs in .vb.

csc CreateResources.cs
CreateResources

resgen AppResources.resx

csc GetStream.cs -resource:AppResources.resources

Im folgenden Beispiel wird die ResourceManager.GetObject(String) -Methode verwendet, um ein benutzerdefiniertes Objekt zu deserialisieren. Das Beispiel enthält eine Quellcodedatei mit dem Namen UIElements.cs (UIElements.vb für Visual Basic), die die folgende Struktur mit dem Namen PersonTabledefiniert. Diese Struktur soll von einer allgemeinen Tabellen-Anzeigeroutine verwendet werden, die den lokalisierten Namen der Tabellenspalten anzeigt. Beachten Sie, dass die PersonTable -Struktur ist mit dem SerializableAttribute -Attribut gekennzeichnet ist.

using System;

[Serializable] public struct PersonTable
{
   public readonly int nColumns;
   public readonly string column1;
   public readonly string column2;
   public readonly string column3;
   public readonly int width1;
   public readonly int width2;
   public readonly int width3;

   public PersonTable(string column1, string column2, string column3,
                  int width1, int width2, int width3)
   {
      this.column1 = column1;
      this.column2 = column2;
      this.column3 = column3;
      this.width1 = width1;
      this.width2 = width2;
      this.width3 = width3;
      this.nColumns = typeof(PersonTable).GetFields().Length / 2;
   }
}
<Serializable> Public Structure PersonTable
    Public ReadOnly nColumns As Integer
    Public Readonly column1 As String
    Public ReadOnly column2 As String
    Public ReadOnly column3 As String
    Public ReadOnly width1 As Integer
    Public ReadOnly width2 As Integer
    Public ReadOnly width3 As Integer

    Public Sub New(column1 As String, column2 As String, column3 As String,
                   width1 As Integer, width2 As Integer, width3 As Integer)
        Me.column1 = column1
        Me.column2 = column2
        Me.column3 = column3
        Me.width1 = width1
        Me.width2 = width2
        Me.width3 = width3
        Me.nColumns = Me.GetType().GetFields().Count \ 2
    End Sub
End Structure

Der folgende Code aus einer Datei mit dem Namen CreateResources.cs (CreateResources.vb für Visual Basic) erstellt eine XML-Ressourcendatei mit dem Namen UIResources.resx, die einen Tabellentitel und ein PersonTable -Objekt speichert, das Informationen für eine App enthält, die für die englische Sprache lokalisiert ist.

using System;
using System.Resources;

public class CreateResource
{
   public static void Main()
   {
      PersonTable table = new PersonTable("Name", "Employee Number",
                                          "Age", 30, 18, 5);
      ResXResourceWriter rr = new ResXResourceWriter(@".\UIResources.resx");
      rr.AddResource("TableName", "Employees of Acme Corporation");
      rr.AddResource("Employees", table);
      rr.Generate();
      rr.Close();
   }
}
Imports System.Resources

Module CreateResource
    Public Sub Main()
        Dim table As New PersonTable("Name", "Employee Number", "Age", 30, 18, 5)
        Dim rr As New ResXResourceWriter(".\UIResources.resx")
        rr.AddResource("TableName", "Employees of Acme Corporation")
        rr.AddResource("Employees", table)
        rr.Generate()
        rr.Close()
    End Sub
End Module

Der folgende Code in eine Quellcodedatei mit dem Namen GetObject.cs (GetObject.vb) ruft dann die Ressourcen ab und zeigt sie auf der Konsole an.

using System;
using System.Resources;

[assembly: NeutralResourcesLanguageAttribute("en")]

public class Example
{
   public static void Main()
   {
      string fmtString = String.Empty;
      ResourceManager rm = new ResourceManager("UIResources", typeof(Example).Assembly);
      string title = rm.GetString("TableName");
      PersonTable tableInfo = (PersonTable) rm.GetObject("Employees");

      if (! String.IsNullOrEmpty(title)) {
         fmtString = "{0," + ((Console.WindowWidth + title.Length) / 2).ToString() + "}";
         Console.WriteLine(fmtString, title);
         Console.WriteLine();
      }

      for (int ctr = 1; ctr <= tableInfo.nColumns; ctr++) {
         string columnName = "column"  + ctr.ToString();
         string widthName = "width" + ctr.ToString();
         string value = tableInfo.GetType().GetField(columnName).GetValue(tableInfo).ToString();
         int width = (int) tableInfo.GetType().GetField(widthName).GetValue(tableInfo);
         fmtString = "{0,-" + width.ToString() + "}";
         Console.Write(fmtString, value);
      }
      Console.WriteLine();
   }
}
Imports System.Resources

<Assembly: NeutralResourcesLanguageAttribute("en")>

Module Example
    Public Sub Main()
        Dim fmtString As String = String.Empty
        Dim rm As New ResourceManager("UIResources", GetType(Example).Assembly)
        Dim title As String = rm.GetString("TableName")
        Dim tableInfo As PersonTable = DirectCast(rm.GetObject("Employees"), PersonTable)

        If Not String.IsNullOrEmpty(title) Then
            fmtString = "{0," + ((Console.WindowWidth + title.Length) \ 2).ToString() + "}"
            Console.WriteLine(fmtString, title)
            Console.WriteLine()
        End If

        For ctr As Integer = 1 To tableInfo.nColumns
            Dim columnName As String = "column" + ctr.ToString()
            Dim widthName As String = "width" + ctr.ToString()
            Dim value As String = CStr(tableInfo.GetType().GetField(columnName).GetValue(tableInfo))
            Dim width As Integer = CInt(tableInfo.GetType().GetField(widthName).GetValue(tableInfo))
            fmtString = "{0,-" + width.ToString() + "}"
            Console.Write(fmtString, value)
        Next
        Console.WriteLine()
    End Sub
End Module

Mit der folgenden Batchdatei können Sie die erforderliche Ressourcendatei und Assemblys erstellen und die App ausführen. Verwenden Sie die Option /r , um Resgen.exe einen Verweis auf UIElements.dll bereitzustellen, damit die Anwendung Zugriff auf Informationen über die PersonTable -Struktur erhält. Wenn Sie C# verwenden, ersetzen Sie den vbc -Compilernamen mit cscund ersetzen Sie die .vb -Erweiterung mit .cs.

vbc -t:library UIElements.vb
vbc CreateResources.vb -r:UIElements.dll
CreateResources

resgen UIResources.resx  -r:UIElements.dll
vbc GetObject.vb -r:UIElements.dll -resource:UIResources.resources

GetObject.exe

Versionsunterstützung für Satellitenassemblys

Wenn das ResourceManager -Objekt die angeforderten Ressourcen abruft, sucht es standardmäßig nach Satellitenassemblys, die Versionsnummern haben, die mit der Versionsnummer der Hauptassembly übereinstimmen. Nachdem Sie eine App bereitgestellt haben, möchten Sie vielleicht die Hauptassembly oder bestimmte Ressourcen-Satellitenassemblys aktualisieren. .NET Framework bietet Unterstützung für die Versionskontrolle der Hauptassembly und Satellitenassemblys.

Das SatelliteContractVersionAttribute-Attribut bietet Unterstützung für die Versionsverwaltung einer Hauptassembly. Wenn Sie dieses Attribut für die Hauptassembly einer Anwendung angeben, können Sie eine Hauptassembly aktualisieren und erneut bereitstellen, ohne die Satellitenassemblys aktualisieren zu müssen. Nach der Aktualisierung der Hauptassembly erhöhen Sie die Haupt-Assembly-Versionsnummer, lassen aber die Nummer der Satellitenvertragsversion unverändert. Wenn der Ressourcen-Manager angeforderte Ressourcen abruft, wird die Version der Satelliten-Assembly, die durch dieses Attribut angegeben wird, geladen.

Herausgeberrichtlinienassemblys bieten Unterstützung für die Versionskontrolle von Satellitenassemblys. Sie können eine Satellitenassembly aktualisieren und erneut bereitstellen, ohne die Hauptassembly aktualisieren zu müssen. Nach der Aktualisierung einer Satellitenassembly erhöhen Sie die Versionsnummer und versenden Sie diese mit der Herausgeberrichtlinienassembly. Geben Sie in der Herausgeberrichtlinienassembly an, dass die neue Satellitenassembly abwärtskompatibel mit der vorherigen Version ist. Der Ressourcen-Manager verwendet das SatelliteContractVersionAttribute -Attribut, um die Version der Satellitenassembly zu bestimmen, aber das Assemblyladeprogramm wird die Version der Satellitenassembly übernehmen, die durch die Herausgeberrichtlinie angegeben ist. Weitere Informationen zur Herausgeberrichtlinienassemblys finden Sie unter Erstellen einer Herausgeberrichtliniendatei.

Um vollständige Assemblyversionsunterstützung zu aktivieren, wird empfohlen, Assemblys mit starkem Namen im globalen Assemblycache und Assemblys ohne starken Namen im Anwendungsverzeichnis bereitzustellen. Wenn Sie Assemblys mit starkem Namen im Anwendungsverzeichnis bereitstellen möchten, werden Sie nicht in der Lage sein, eine Satellitenassembly-Versionsnummer zu erhöhen, wenn Sie die Assembly aktualisieren. Stattdessen müssen Sie ein direktes Update ausführen, wobei Sie den vorhandenen Code durch den aktualisierten Code ersetzen und die Versionsnummer beibehalten. Wenn Sie beispielsweise Version 1.0.0.0 einer Satellitenassembly mit dem vollständig angegebenen Assemblynamen „myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a“ aktualisieren möchten, überschreiben Sie sie mit der aktualisierten myApp.resources.dll, die mit dem gleichen, vollständig angegebenen Assemblynamen „myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a“ kompiliert wurde. Beachten Sie, dass die Verwendung direkter Updates für Satelliten-Assemblydateien es schwierig für eine App macht, die Version einer Satellitenassembly genau zu bestimmen.

Weitere Informationen zur Versionsverwaltung von Assemblys finden Sie unter Versionsverwaltung von Assemblys und So sucht die Runtime nach Assemblys.

Abrufen von Ressourcen aus RESOURCES-Dateien

Wenn Sie keine Ressourcen in Satellitenassemblys bereitstellen wollen, können Sie weiterhin ein ResourceManager -Objekt für den direkten Zugriff auf Ressourcen in Ressourcendateien verwenden. Zu diesem Zweck müssen Sie die Ressourcendateien korrekt bereitstellen. Verwenden Sie dann die ResourceManager.CreateFileBasedResourceManager -Methode zum Instanziieren eines ResourceManager -Objekts und geben Sie das Verzeichnis an, das die eigenständigen Ressourcendateien enthält.

Bereitstellen von RESOURCES-Dateien

Beim Einbetten von Ressourcendateien in eine Anwendungsassembly und Satellitenassemblys hat jede Satellitenassembly den gleichen Dateinamen, befindet sich jedoch in einem Unterverzeichnis, das die Kultur der Satellitenassembly wiedergibt. Wenn Sie direkt aus Ressourcendateien auf Ressourcen zugreifen, können Sie hingegen alle Ressourcendateien in einem Verzeichnis platzieren, in der Regel in einem Unterverzeichnis des Anwendungsverzeichnisses. Der Name des Standard-Ressourcendateien der App besteht nur aus einem Stammnamen ohne Angabe seiner Kultur (z.B. strings.resources). Die Ressourcen für jede lokalisierte Kultur werden in einer Datei gespeichert, deren Name aus dem Stammnamen gefolgt von der Kultur besteht (z.B. strings.ja.resources oder strings.de-DE.resources).

Die folgende Abbildung zeigt, wo Ressourcendateien in der Verzeichnisstruktur platziert werden sollen. Sie verdeutlicht auch die Benennungskonventionen für RESOURCES-Dateien.

Abbildung des Hauptverzeichnisses der Anwendung

Verwenden des Ressourcen-Managers

Nachdem Sie Ihre Ressourcen erstellt und im richtigen Verzeichnis gespeichert haben, erstellen Sie ein ResourceManager -Objekt, um die Ressourcen durch Aufrufen der CreateFileBasedResourceManager(String, String, Type) -Methode zu verwenden. Der erste Parameter gibt den Stammnamen der Standard-Ressourcendatei der App an (dies wäre „strings“ für das Beispiel im vorherigen Abschnitt). Der zweite Parameter gibt den Speicherort der Ressourcen an („Resources“ im vorherigen Beispiel). Der dritte Parameter gibt die zu verwendende ResourceSet -Implementierung an. Wenn der dritte Parameter nullist, wird das Standard-Laufzeit ResourceSet verwendet.

Hinweis

Stellen Sie keine ASP.NET-Apps mit eigenständigen Ressourcendateien bereit. Dies kann zu Sperrproblemen führen und unterbricht die XCOPY-Bereitstellung. Es wird empfohlen, dass Sie ASP.NET-Ressourcen in Satellitenassemblys bereitstellen. Weitere Informationen finden Sie unter ASP.NET Web Page Resources Overview.

Nach dem Instanziieren des ResourceManager -Objekts verwenden Sie die GetString, GetObjectund GetStream -Methoden wie bereits erwähnt, um die Ressourcen abzurufen. Das direkte Abrufen von Ressourcen aus Ressourcendateien unterscheidet sich jedoch von dem Abruf von eingebetteten Ressourcen aus Assemblys. Beim Abrufen von Ressourcen aus Ressourcendateien rufen die Methoden GetString(String), GetObject(String)und GetStream(String) immer die Standardkultur-Ressourcen ab, unabhängig von der aktuellen Kultur. Um die Ressourcen der aktuellen Kultur der Anwendung oder einer anderen bestimmten Kultur abrufen zu können, müssen Sie die GetString(String, CultureInfo)-, GetObject(String, CultureInfo)- oder GetStream(String, CultureInfo)-Methode aufrufen und die Kultur angeben, deren Ressourcen abgerufen werden sollen. Um die Ressourcen der aktuellen Kultur abzurufen, geben Sie den Wert der CultureInfo.CurrentCulture -Eigenschaft als culture Argument an. Wenn der Ressourcen-Manager die Ressourcen von culturenicht abrufen kann, verwendet er die Standard-Ressourcen-Fallback-Regeln, um die entsprechenden Ressourcen abzurufen.

Beispiel

Im folgenden Beispiel wird veranschaulicht, wie der Ressourcen-Manager Ressourcen direkt aus einer Ressourcendatei abruft. Das Beispiel besteht aus drei textbasierten Ressourcendateien für die Kulturen Englisch (USA), Französisch (Frankreich) und Russisch (Russische Föderation). Englisch (USA) ist die Standardkultur in dem Beispiel. Die Ressourcen werden in der folgenden Datei mit dem Namen Strings.txt gespeichert:

Greeting=Hello
Prompt=What is your name?

Ressourcen für die Kultur Französisch (Frankreich) befinden sich in der folgenden Datei mit dem Namen Strings.fr-FR.txt:

Greeting=Bon jour
Prompt=Comment vous appelez-vous?

Ressourcen für die Kultur Russisch (Russische Föderation) befinden sich in der folgenden Datei mit dem Namen Strings.ru-RU.txt:

Greeting=Здравствуйте
Prompt=Как вас зовут?

Der Quellcode für das Beispiel lautet wie folgt. Das Beispiel instanziiert CultureInfo -Objekte für die Kulturen Englisch (USA), Englisch (Kanada), Französisch (Frankreich) und Russisch (Russische Föderation) und macht diese jeweils zur aktuellen Kultur. Die ResourceManager.GetString(String, CultureInfo) -Methode stellt dann den Wert der CultureInfo.CurrentCulture -Eigenschaft als culture Argument bereit, um die entsprechenden kulturspezifischen Ressourcen abzurufen.

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguage("en-US")]

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "en-CA", "ru-RU", "fr-FR" };
      ResourceManager rm = ResourceManager.CreateFileBasedResourceManager("Strings", "Resources", null);

      foreach (var cultureName in cultureNames) {
         Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         string greeting = rm.GetString("Greeting", CultureInfo.CurrentCulture);
         Console.WriteLine("\n{0}!", greeting);
         Console.Write(rm.GetString("Prompt", CultureInfo.CurrentCulture));
         string name = Console.ReadLine();
         if (! String.IsNullOrEmpty(name))
            Console.WriteLine("{0}, {1}!", greeting, name);
      }
      Console.WriteLine();
   }
}
// The example displays output like the following:
//       Hello!
//       What is your name? Dakota
//       Hello, Dakota!
//
//       Hello!
//       What is your name? Koani
//       Hello, Koani!
//
//       Здравствуйте!
//       Как вас зовут?Samuel
//       Здравствуйте, Samuel!
//
//       Bon jour!
//       Comment vous appelez-vous?Yiska
//       Bon jour, Yiska!
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly: NeutralResourcesLanguageAttribute("en-US")>

Module Example
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "en-CA", "ru-RU", "fr-FR"}
        Dim rm As ResourceManager = ResourceManager.CreateFileBasedResourceManager("Strings", "Resources", Nothing)

        For Each cultureName In cultureNames
            Console.WriteLine()
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
            Dim greeting As String = rm.GetString("Greeting", CultureInfo.CurrentCulture)
            Console.WriteLine("{0}!", greeting)
            Console.Write(rm.GetString("Prompt", CultureInfo.CurrentCulture))
            Dim name As String = Console.ReadLine()
            If Not String.IsNullOrEmpty(name) Then
                Console.WriteLine("{0}, {1}!", greeting, name)
            End If
        Next
        Console.WriteLine()
    End Sub
End Module
' The example displays output like the following:
'       Hello!
'       What is your name? Dakota
'       Hello, Dakota!
'       
'       Hello!
'       What is your name? Koani
'       Hello, Koani!
'       
'       Здравствуйте!
'       Как вас зовут?Samuel
'       Здравствуйте, Samuel!
'       
'       Bon jour!
'       Comment vous appelez-vous?Yiska
'       Bon jour, Yiska!

Sie können die C#-Version des Beispiels kompilieren, indem Sie die folgende Batchdatei ausführen. Wenn Sie Visual Basic verwenden, ersetzen Sie csc mit vbc und ersetzen Sie die Erweiterung .cs mit .vb.

md Resources
resgen Strings.txt Resources\Strings.resources
resgen Strings.fr-FR.txt Resources\Strings.fr-FR.resources
resgen Strings.ru-RU.txt Resources\Strings.ru-RU.resources

csc Example.cs

Siehe auch