Freigeben über


Abrufen von Ressourcen in .NET-Apps

Wenn Sie mit lokalisierten Ressourcen in .NET-Apps arbeiten, sollten Sie die Ressourcen für die Standard- oder neutrale Kultur ideal mit der Hauptassembly verpacken und eine separate Satellitenassembly für jede Von Ihrer App unterstützte Sprache oder Kultur erstellen. Anschließend können Sie die ResourceManager Klasse wie im nächsten Abschnitt beschrieben verwenden, um auf benannte Ressourcen zuzugreifen. Wenn Sie Ihre Ressourcen nicht in die Hauptassembly und Satellitenassemblys einbetten möchten, können Sie auch direkt auf binäre .resources-Dateien zugreifen, wie im Abschnitt Ressourcen aus .resources-Dateien abrufen später in diesem Artikel beschrieben.

Abrufen von Ressourcen aus Assemblys

Die ResourceManager Klasse bietet Zugriff auf Ressourcen zur Laufzeit. Sie verwenden die ResourceManager.GetString Methode, um Zeichenfolgenressourcen und die ResourceManager.GetObject Methode ResourceManager.GetStream zum Abrufen von Ressourcen ohne Zeichenfolge abzurufen. Jede Methode enthält zwei Überladungen:

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

  • Eine Überladung mit zwei Parametern: eine Zeichenfolge mit dem Namen der Ressource und ein CultureInfo Objekt, das die Kultur darstellt, deren Ressource abgerufen werden soll. Wenn ein Ressourcensatz für diese Kultur nicht gefunden werden kann, verwendet der Ressourcen-Manager Fallbackregeln, um eine entsprechende Ressource abzurufen. Weitere Informationen finden Sie unter " GetString(String, CultureInfo), GetObject(String, CultureInfo)" und GetStream(String, CultureInfo) "Methoden".

Der Ressourcenmanager verwendet den Ressourcenfallbackprozess, um zu steuern, wie die App kulturspezifische Ressourcen abruft. Weitere Informationen finden Sie im Abschnitt "Ressourcenfallbackprozess" in Package and deploy resources. Informationen zum Instanziieren eines ResourceManager Objekts finden Sie im Abschnitt "Instanziieren eines ResourceManager-Objekts" im ResourceManager Klassenthema.

Beispiel zum Abrufen von Zeichenfolgendaten

Im folgenden Beispiel wird die GetString(String) Methode aufgerufen, um die Zeichenfolgenressourcen der aktuellen Benutzeroberflächenkultur 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) befindet sich in einer Datei mit dem Namen Strings.txt:

TimeHeader=The current time is

Die Ressource Französisch (Frankreich) befindet sich in einer Datei mit dem Namen Strings.fr-FR.txt:

TimeHeader=L'heure actuelle est

Die Russische Ressource (Russland) befindet sich in einer Datei mit dem Namen Strings.ru-RU.txt:

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

Der Quellcode für dieses Beispiel, das sich in einer Datei namens GetString.cs für die C#-Version des Codes und GetString.vb für die Visual Basic-Version befindet, definiert ein Zeichenfolgenarray, das den Namen von vier Kulturen enthält: die drei Kulturen, für die Ressourcen verfügbar sind, und die spanische Kultur (Spanien). Eine Schleife, die fünfmal ausgeführt wird, wählt jedes Mal zufällig eine dieser Kulturen aus und weist sie den Eigenschaften Thread.CurrentCulture und CultureInfo.CurrentUICulture zu. Anschließend wird die GetString(String) Methode aufgerufen, um die lokalisierte Zeichenfolge abzurufen, die zusammen mit der Tageszeit 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: {culture.NativeName}");
         string timeString = rm.GetString("TimeHeader");
         Console.WriteLine($"{timeString} {DateTime.Now:T}\n");
      }
   }
}
// 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) kompiliert das Beispiel und generiert Satellitenassemblys in den entsprechenden Verzeichnissen. Die Befehle werden für die C#-Sprache und den Compiler bereitgestellt. Wechseln Sie csc für Visual Basic zu vbc, und wechseln Sie GetString.cs zu 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 Benutzeroberflächenkultur Spanisch (Spanien) ist, beachten Sie, dass im Beispiel Englische Sprachressourcen angezeigt werden, da spanischsprachige Ressourcen nicht verfügbar sind und Englisch die Standardkultur des Beispiels ist.

Abrufen von Objektdatenbeispielen

Sie können die Methoden GetObject und GetStream verwenden, um Objektdaten abzurufen. Dazu gehören primitive Datentypen, serialisierbare Objekte und Objekte, die im Binärformat (z. B. Bilder) gespeichert sind.

Im folgenden Beispiel wird die GetStream(String) Methode verwendet, um eine Bitmap abzurufen, die im öffnenden Begrüßungsfenster einer App verwendet wird. 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 mit dem Namen SplashScreen.jpggeladen; Sie können den Dateinamen ändern, um Ihr eigenes Bild zu ersetzen.

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 an.

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 für Visual Basic csc zu vbc, und ändern Sie die Erweiterung der Quellcodedatei von .cs zu .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 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 Tabellenanzeigeroutine verwendet werden, die lokalisierte Namen von Tabellenspalten anzeigt. Beachten Sie, dass die PersonTable Struktur 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 namens CreateResources.cs (CreateResources.vb für Visual Basic) erstellt eine XML-Ressourcendatei namens "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 einer Quellcodedatei namens GetObject.cs (GetObject.vb) ruft dann die Ressourcen ab und zeigt sie in 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

Sie können die erforderliche Ressourcendatei und Assemblys erstellen und die App ausführen, indem Sie die folgende Batchdatei ausführen. Sie müssen die /r Option verwenden, um Resgen.exe mit einem Verweis auf UIElements.dll anzugeben, damit sie auf Informationen zur PersonTable Struktur zugreifen kann. Wenn Sie C# verwenden, ersetzen Sie den vbc Compilernamen durch csc, und ersetzen Sie die .vb Erweiterung durch .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 angeforderte Ressourcen abruft, sucht es standardmäßig nach Satellitenassemblys mit Versionsnummern, die der Versionsnummer der Hauptassembly entsprechen. 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 Versionsverwaltung der Hauptassemblys und Satellitenassemblys.

Das SatelliteContractVersionAttribute Attribut bietet Versionsverwaltungsunterstützung für eine Hauptassembly. Wenn Sie dieses Attribut für die Hauptassembly einer App angeben, können Sie eine Hauptassembly aktualisieren und erneut bereitstellen, ohne die Satellitenassemblys zu aktualisieren. Nachdem Sie die Hauptassembly aktualisiert haben, erhöhen Sie die Versionsnummer der Hauptassembly, lassen aber die Versionsnummer des Satellitenvertrags unverändert. Wenn der Ressourcen-Manager angeforderte Ressourcen abruft, lädt er die Version der Satellitenassembly, die durch dieses Attribut angegeben wird.

Herausgeberrichtlinienassemblys bieten Unterstützung für die Versionskontrolle von Satellitenassemblys. Sie können eine Satellitenassembly aktualisieren und erneut bereitstellen, ohne die Hauptassembly zu aktualisieren. 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 die Unterstützung für die vollständige Assemblyversionsverwaltung zu aktivieren, empfehlen wir, dass Sie stark benannte Assemblys im globalen Assemblycache bereitstellen und Assemblys bereitstellen, die keine starken Namen im Anwendungsverzeichnis haben. Wenn Sie stark benannte Assemblys im Anwendungsverzeichnis bereitstellen möchten, können Sie die Versionsnummer einer Satellitenassembly nicht erhöhen, wenn Sie die Assembly aktualisieren. Stattdessen müssen Sie ein direktes Update durchführen, bei dem Sie den vorhandenen Code durch den aktualisierten Code ersetzen und dieselbe 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.0, aktualisieren möchten, Culture=de, PublicKeyToken=b03f5f11d50a3a", überschreiben Sie es mit der aktualisierten myApp.resources.dll, die mit demselben, vollständig angegebenen Assemblynamen "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a" kompiliert wurde. Beachten Sie, dass die Verwendung von In-Place-Updates für Satellitenassemblydateien es einer App erschwert, die Version einer Satellitenassembly genau zu bestimmen.

Weitere Informationen zur Assemblyversionsverwaltung finden Sie unter Assemblyversionsverwaltung und Wie die Runtime Assemblyassemblys findet.

Abrufen von Ressourcen aus .resources-Dateien

Wenn Sie sich entscheiden, Ressourcen nicht in Satellitenassemblys bereitzustellen, können Sie weiterhin ein ResourceManager-Objekt verwenden, um direkt auf Ressourcen aus Ressourcendateien zuzugreifen. Dazu müssen Sie die .resources-Dateien korrekt bereitstellen. Anschließend verwenden Sie die ResourceManager.CreateFileBasedResourceManager Methode, um ein ResourceManager Objekt zu instanziieren und das Verzeichnis anzugeben, das die eigenständigen RESSOURCEN-Dateien enthält.

Bereitstellen von .resources-Dateien

Wenn Sie .resources Dateien in Anwendungsassemblys und Satellitenassemblys einbetten, hat jede Satellitenassembly denselben Dateinamen, wird jedoch in einem Unterverzeichnis platziert, das die Kultur der Satellitenassembly widerspiegelt. Im Gegensatz dazu können Sie, wenn Sie direkt auf Ressourcen aus RESSOURCENdateien zugreifen, alle RESSOURCEN-Dateien in einem einzigen Verzeichnis, in der Regel ein Unterverzeichnis des Anwendungsverzeichnisses, platzieren. Der Name der Standardmäßig-RESSOURCEN-Datei der App besteht nur aus einem Stammnamen, ohne angabe der 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 Zeichenfolgen.de-DE.resources).

Die folgende Abbildung zeigt, wo sich Ressourcendateien in der Verzeichnisstruktur befinden sollen. Außerdem werden die Benennungskonventionen für .resource-Dateien festgelegt.

Abbildung, die das Hauptverzeichnis für Ihre Anwendung zeigt.

Verwenden des Ressourcen-Managers

Nachdem Sie Ihre Ressourcen erstellt und im entsprechenden Verzeichnis abgelegt haben, erstellen Sie ein ResourceManager Objekt, um die Ressourcen zu verwenden, indem Sie die CreateFileBasedResourceManager(String, String, Type) Methode aufrufen. Der erste Parameter gibt den Stammnamen der Standardressourcendatei der App an (dies wäre "strings" für das Beispiel im vorherigen Abschnitt). Der zweite Parameter gibt den Speicherort der Ressourcen an ("Ressourcen" für das vorherige Beispiel). Der dritte Parameter gibt die ResourceSet zu verwendende Implementierung an. Wenn der dritte Parameter lautet null, wird die Standardlaufzeit ResourceSet verwendet.

Hinweis

Stellen Sie ASP.NET Apps nicht mithilfe eigenständiger RESSOURCENdateien bereit. Dies kann zu Sperrfehlern führen und die XCOPY-Bereitstellung beeinträchtigen. Wir empfehlen, ASP.NET-Ressourcen in Satellitenassemblys bereitzustellen. Weitere Informationen finden Sie unter ASP.NET Web Page Resources Overview.

Nachdem Sie das ResourceManager-Objekt instanziieren, verwenden Sie die GetString, GetObject und GetStream Methoden, wie zuvor beschrieben, um die Ressourcen abzurufen. Der Abruf von Ressourcen direkt aus .resources-Dateien unterscheidet sich jedoch vom Abruf eingebetteter Ressourcen aus Assemblys. Wenn Sie Ressourcen aus Ressourcen-Dateien abrufen, rufen die GetString(String), GetObject(String) und GetStream(String) Methoden unabhängig von der aktuellen Kultur immer die Ressourcen der Standardkultur ab. Um die Ressourcen der aktuellen Kultur der App oder einer bestimmten Kultur abzurufen, müssen Sie die Methoden GetString(String, CultureInfo), GetObject(String, CultureInfo) oder GetStream(String, CultureInfo) 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 culturenicht abrufen kann, verwendet er die standardmäßigen Ressourcenfallbackregeln, um die entsprechenden Ressourcen abzurufen.

Beispiel

Das folgende Beispiel veranschaulicht, wie der Ressourcen-Manager Ressourcen direkt aus .resources-Dateien abruft. Das Beispiel besteht aus drei textbasierten Ressourcendateien für die Kulturen Englisch (USA), Französisch (Frankreich) und Russisch (Russland). Englisch (USA) ist die Standardkultur des Beispiels. Die Ressourcen werden in der folgenden Datei namens Strings.txtgespeichert:

Greeting=Hello
Prompt=What is your name?

Ressourcen für die französische Kultur (Frankreich) werden in der folgenden Datei gespeichert, die Strings.fr-FR.txtheißt:

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

Ressourcen für die russische Kultur (Russland) werden in der folgenden Datei gespeichert, die Strings.ru-RU.txtheißt:

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

Im Folgenden sehen Sie den Quellcode für das Beispiel. 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 zum Abrufen der entsprechenden kulturspezifischen Ressourcen bereit.

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{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 diese durch cscvbc, und ersetzen Sie die .cs Erweiterung durch .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