System.Resources.ResourceReader-Klasse

Dieser Artikel enthält ergänzende Hinweise zur Referenzdokumentation für diese API.

Wichtig

Das Aufrufen von Methoden aus dieser Klasse mit nicht vertrauenswürdigen Daten stellt ein Sicherheitsrisiko dar. Rufen Sie die Methoden aus dieser Klasse nur mit vertrauenswürdigen Daten auf. Weitere Informationen finden Sie unter Überprüfen aller Eingaben.

Die ResourceReader Klasse stellt eine Standardimplementierung der IResourceReader Schnittstelle bereit. Eine ResourceReader Instanz stellt entweder eine eigenständige RESSOURCEN-Datei oder eine RESSOURCEN-Datei dar, die in eine Assembly eingebettet ist. Sie wird verwendet, um die Ressourcen in einer RESSOURCENdatei aufzählen und dessen Name/Wert-Paare abzurufen. Sie unterscheidet sich von der ResourceManager Klasse, die verwendet wird, um angegebene benannte Ressourcen aus einer RESSOURCEN-Datei abzurufen, die in eine Assembly eingebettet ist. Die ResourceManager Klasse wird verwendet, um Ressourcen abzurufen, deren Namen im Voraus bekannt sind, während die ResourceReader Klasse zum Abrufen von Ressourcen nützlich ist, deren Anzahl oder genaue Namen zur Kompilierungszeit nicht bekannt sind. Beispielsweise kann eine Anwendung eine Ressourcendatei verwenden, um Konfigurationsinformationen zu speichern, die in Abschnitten und Elementen in einem Abschnitt organisiert sind, wobei die Anzahl der Abschnitte oder Elemente in einem Abschnitt im Voraus nicht bekannt ist. Ressourcen können dann generisch (z Section1. B. , Section1Item1, Section1Item2usw.) benannt und mithilfe eines ResourceReader Objekts abgerufen werden.

Wichtig

Dieser Typ implementiert die IDisposable-Schnittstelle. Nach Abschluss der Verwendung sollten Sie den Typ entweder direkt oder indirekt löschen. Zum direkten Löschen des Typs rufen Sie seine Dispose-Methode in einem try/catch-Block auf. Zum indirekten Löschen verwenden Sie ein Sprachkonstrukt wie using (in C#) oder Using (in Visual Basic). Weitere Informationen finden Sie im Abschnitt "Verwenden eines Objekts, das IDisposable implementiert" in der IDisposable Schnittstellendokumentation.

Instanziieren eines ResourceReader-Objekts

Eine RESSOURCEN-Datei ist eine Binärdatei, die entweder aus einer Textdatei oder einer XML-RESX-Datei durch Resgen.exe (Ressourcendatei-Generator) kompiliert wurde. Ein ResourceReader Objekt kann entweder eine eigenständige RESSOURCEN-Datei oder eine RESSOURCEN-Datei darstellen, die in eine Assembly eingebettet wurde.

Um ein ResourceReader Objekt zu instanziieren, das aus einer eigenständigen RESSOURCEN-Datei liest, verwenden Sie den ResourceReader Klassenkonstruktor entweder mit einem Eingabedatenstrom oder einer Zeichenfolge, die den Dateinamen der RESSOURCEN enthält. Im folgenden Beispiel werden beide Ansätze veranschaulicht. Das erste Instanziiert ein ResourceReader Objekt, das eine RESSOURCEN-Datei Resources1.resources mit dem Dateinamen darstellt. Der zweite Instanziiert ein ResourceReader Objekt, das eine RESSOURCEN-Datei darstellt, die mithilfe eines aus der Datei erstellten Datenstroms benannt Resources2.resources wird.

// Instantiate a standalone .resources file from its filename.
var rr1 = new System.Resources.ResourceReader("Resources1.resources");

// Instantiate a standalone .resources file from a stream.
var fs = new System.IO.FileStream(@".\Resources2.resources",
                                  System.IO.FileMode.Open);
var rr2 = new System.Resources.ResourceReader(fs);
' Instantiate a standalone .resources file from its filename.
Dim rr1 As New System.Resources.ResourceReader("Resources1.resources")

' Instantiate a standalone .resources file from a stream.
Dim fs As New System.IO.FileStream(".\Resources2.resources",
                                   System.IO.FileMode.Open)
Dim rr2 As New System.Resources.ResourceReader(fs)

Um ein ResourceReader Objekt zu erstellen, das eine eingebettete RESSOURCEN-Datei darstellt, instanziieren Sie ein Assembly Objekt aus der Assembly, in die die RESSOURCEN-Datei eingebettet ist. Die Assembly.GetManifestResourceStream Methode gibt ein Stream Objekt zurück, das an den ResourceReader(Stream) Konstruktor übergeben werden kann. Im folgenden Beispiel wird ein ResourceReader Objekt instanziiert, das eine eingebettete RESSOURCEN-Datei darstellt.

System.Reflection.Assembly assem =
             System.Reflection.Assembly.LoadFrom(@".\MyLibrary.dll");
System.IO.Stream fs =
             assem.GetManifestResourceStream("MyCompany.LibraryResources.resources");
var rr = new System.Resources.ResourceReader(fs);
Dim assem As System.Reflection.Assembly = 
             System.Reflection.Assembly.LoadFrom(".\MyLibrary.dll") 
Dim fs As System.IO.Stream = 
             assem.GetManifestResourceStream("MyCompany.LibraryResources.resources")
Dim rr As New System.Resources.ResourceReader(fs)

Aufzählen der Ressourcen eines ResourceReader-Objekts

Zum Aufzählen der Ressourcen in einer RESSOURCEN-Datei rufen Sie die GetEnumerator Methode auf, die ein System.Collections.IDictionaryEnumerator Objekt zurückgibt. Sie rufen die IDictionaryEnumerator.MoveNext Methode auf, um von einer Ressource zur nächsten zu wechseln. Die Methode gibt zurück false , wenn alle Ressourcen in der RESSOURCEN-Datei aufgezählt wurden.

Hinweis

Obwohl die ResourceReader Klasse die IEnumerable Schnittstelle und die IEnumerable.GetEnumerator Methode implementiert, stellt die ResourceReader.GetEnumerator Methode die IEnumerable.GetEnumerator Implementierung nicht bereit. Stattdessen gibt die ResourceReader.GetEnumerator Methode ein IDictionaryEnumerator Schnittstellenobjekt zurück, das Zugriff auf das Name/Wert-Paar jeder Ressource ermöglicht.

Sie können die einzelnen Ressourcen in der Sammlung auf zwei Arten abrufen:

Abrufen von Ressourcen mithilfe von IDictionaryEnumerator-Eigenschaften

Die erste Methode zum Aufzählen der Ressourcen in einer RESSOURCEN-Datei umfasst das direkte Abrufen des Namens-/Wertpaars jeder Ressource. Nachdem Sie die IDictionaryEnumerator.MoveNext Methode aufgerufen haben, um zu jeder Ressource in der Auflistung zu wechseln, können Sie den Ressourcennamen aus der IDictionaryEnumerator.Key Eigenschaft und den Ressourcendaten aus der IDictionaryEnumerator.Value Eigenschaft abrufen.

Das folgende Beispiel zeigt, wie Sie den Namen und Wert jeder Ressource in einer RESSOURCEN-Datei mithilfe der und IDictionaryEnumerator.Value der IDictionaryEnumerator.Key Eigenschaften abrufen. Erstellen Sie zum Ausführen des Beispiels die folgende Textdatei namens ApplicationResources.txt, um Zeichenfolgenressourcen zu definieren.

Title="Contact Information"
Label1="First Name:"
Label2="Middle Name:"
Label3="Last Name:"
Label4="SSN:"
Label5="Street Address:"
Label6="City:"
Label7="State:"
Label8="Zip Code:"
Label9="Home Phone:"
Label10="Business Phone:"
Label11="Mobile Phone:"
Label12="Other Phone:"
Label13="Fax:"
Label14="Email Address:"
Label15="Alternate Email Address:"

Sie können die Textdatei dann mithilfe des folgenden Befehls in eine Binärdatei namens ApplicationResources.resources konvertieren:

resgen ApplicationResources.txt

Im folgenden Beispiel wird dann die ResourceReader Klasse zum Aufzählen der einzelnen Ressourcen in der eigenständigen Binärressourcendatei und zum Anzeigen des Schlüsselnamens und des entsprechenden Werts verwendet.

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

public class Example1
{
   public static void Run()
   {
      Console.WriteLine("Resources in ApplicationResources.resources:");
      ResourceReader res = new ResourceReader(@".\ApplicationResources.resources");
      IDictionaryEnumerator dict = res.GetEnumerator();
      while (dict.MoveNext())
         Console.WriteLine("   {0}: '{1}' (Type {2})", 
                           dict.Key, dict.Value, dict.Value.GetType().Name);
      res.Close();
   }
}
// The example displays the following output:
//       Resources in ApplicationResources.resources:
//          Label3: '"Last Name:"' (Type String)
//          Label2: '"Middle Name:"' (Type String)
//          Label1: '"First Name:"' (Type String)
//          Label7: '"State:"' (Type String)
//          Label6: '"City:"' (Type String)
//          Label5: '"Street Address:"' (Type String)
//          Label4: '"SSN:"' (Type String)
//          Label9: '"Home Phone:"' (Type String)
//          Label8: '"Zip Code:"' (Type String)
//          Title: '"Contact Information"' (Type String)
//          Label12: '"Other Phone:"' (Type String)
//          Label13: '"Fax:"' (Type String)
//          Label10: '"Business Phone:"' (Type String)
//          Label11: '"Mobile Phone:"' (Type String)
//          Label14: '"Email Address:"' (Type String)
//          Label15: '"Alternate Email Address:"' (Type String)
Imports System.Collections
Imports System.Resources

Module Example2
    Public Sub Main()
        Console.WriteLine("Resources in ApplicationResources.resources:")
        Dim res As New ResourceReader(".\ApplicationResources.resources")
        Dim dict As IDictionaryEnumerator = res.GetEnumerator()
        Do While dict.MoveNext()
            Console.WriteLine("   {0}: '{1}' (Type {2})", dict.Key, dict.Value, dict.Value.GetType().Name)
        Loop
        res.Close()
    End Sub
End Module
' The example displays output like the following:
'       Resources in ApplicationResources.resources:
'          Label3: '"Last Name:"' (Type String)
'          Label2: '"Middle Name:"' (Type String)
'          Label1: '"First Name:"' (Type String)
'          Label7: '"State:"' (Type String)
'          Label6: '"City:"' (Type String)
'          Label5: '"Street Address:"' (Type String)
'          Label4: '"SSN:"' (Type String)
'          Label9: '"Home Phone:"' (Type String)
'          Label8: '"Zip Code:"' (Type String)
'          Title: '"Contact Information"' (Type String)
'          Label12: '"Other Phone:"' (Type String)
'          Label13: '"Fax:"' (Type String)
'          Label10: '"Business Phone:"' (Type String)
'          Label11: '"Mobile Phone:"' (Type String)
'          Label14: '"Email Address:"' (Type String)
'          Label15: '"Alternate Email Address:"' (Type String)

Der Versuch, Ressourcendaten aus der IDictionaryEnumerator.Value Eigenschaft abzurufen, kann die folgenden Ausnahmen auslösen:

  • A FormatException , wenn die Daten nicht im erwarteten Format vorliegen.
  • A FileNotFoundException , wenn die Assembly, die den Typ enthält, zu dem die Daten gehören, nicht gefunden werden kann.
  • A TypeLoadException , wenn der Typ, zu dem die Daten gehören, nicht gefunden werden kann.

In der Regel werden diese Ausnahmen ausgelöst, wenn die RESSOURCEN-Datei manuell geändert wurde, wenn die Assembly, in der ein Typ definiert ist, entweder nicht in einer Anwendung enthalten oder versehentlich gelöscht wurde, oder wenn die Assembly eine ältere Version ist, die vor einem Typ liegt. Wenn eine dieser Ausnahmen ausgelöst wird, können Sie Ressourcen abrufen, indem Sie jede Ressource aufzählen und die GetResourceData Methode aufrufen, wie im folgenden Abschnitt gezeigt. Dieser Ansatz bietet Ihnen einige Informationen zum Datentyp, den die IDictionaryEnumerator.Value Eigenschaft zurückgegeben hat.

Abrufen von Ressourcen nach Namen mit GetResourceData

Der zweite Ansatz zum Aufzählen von Ressourcen in einer RESSOURCENdatei umfasst auch das Navigieren durch die Ressourcen in der Datei durch Aufrufen der IDictionaryEnumerator.MoveNext Methode. Für jede Ressource rufen Sie den Namen der Ressource aus der IDictionaryEnumerator.Key Eigenschaft ab, die dann an die GetResourceData(String, String, Byte[]) Methode übergeben wird, um die Daten der Ressource abzurufen. Dies wird als Bytearray im resourceData Argument zurückgegeben.

Dieser Ansatz ist schwieriger als das Abrufen des Ressourcennamens und -werts aus den und IDictionaryEnumerator.Value den IDictionaryEnumerator.Key Eigenschaften, da er die tatsächlichen Bytes zurückgibt, die den Ressourcenwert bilden. Wenn jedoch der Versuch, die Ressource abzurufen, eine Ausnahme auslöst, kann die GetResourceData Methode helfen, die Quelle der Ausnahme zu identifizieren, indem Informationen zum Datentyp der Ressource bereitgestellt werden. Weitere Informationen zur Zeichenfolge, die den Datentyp der Ressource angibt, finden Sie unter GetResourceData.

Im folgenden Beispiel wird veranschaulicht, wie Sie diesen Ansatz zum Abrufen von Ressourcen und zum Behandeln von Ausnahmen verwenden, die ausgelöst werden. Es erstellt programmgesteuert eine binäre RESSOURCEN-Datei, die vier Zeichenfolgen, einen Booleschen Wert, eine ganze Zahl und eine Bitmap enthält. Gehen Sie wie folgt vor, um das Beispiel auszuführen:

  1. Kompilieren und Ausführen des folgenden Quellcodes, der eine RESSOURCEN-Datei namens ContactResources.resources erstellt.

    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Resources;
    using System.Runtime.Versioning;
    
    public class Example5
    {
        [SupportedOSPlatform("windows")]
        public static void Run()
        {
            // Bitmap as stream.
            MemoryStream bitmapStream = new MemoryStream();
            Bitmap bmp = new Bitmap(@".\ContactsIcon.jpg");
            bmp.Save(bitmapStream, ImageFormat.Jpeg);
    
            // Define resources to be written.
            using (ResourceWriter rw = new ResourceWriter(@".\ContactResources.resources"))
            {
                rw.AddResource("Title", "Contact List");
                rw.AddResource("NColumns", 5);
                rw.AddResource("Icon", bitmapStream);
                rw.AddResource("Header1", "Name");
                rw.AddResource("Header2", "City");
                rw.AddResource("Header3", "State");
                rw.AddResource("ClientVersion", true);
                rw.Generate();
            }
        }
    }
    

    Die Quellcodedatei wird CreateResources.cs benannt. Sie können es in C# kompilieren, indem Sie den folgenden Befehl verwenden:

    csc CreateResources.cs /r:library.dll
    
  2. Kompilieren Sie den folgenden Code, und führen Sie den folgenden Code aus, um die Ressourcen in der Datei ContactResources.resources aufzählen zu können.

    using System;
    using System.Collections;
    using System.Drawing;
    using System.IO;
    using System.Resources;
    using System.Runtime.Versioning;
    
    public class Example6
    {
        [SupportedOSPlatform("windows")]
        public static void Run()
        {
            ResourceReader rdr = new ResourceReader(@".\ContactResources.resources");
            IDictionaryEnumerator dict = rdr.GetEnumerator();
            while (dict.MoveNext())
            {
                Console.WriteLine("Resource Name: {0}", dict.Key);
                try
                {
                    Console.WriteLine("   Value: {0}", dict.Value);
                }
                catch (FileNotFoundException)
                {
                    Console.WriteLine("   Exception: A file cannot be found.");
                    DisplayResourceInfo(rdr, (string)dict.Key, false);
                }
                catch (FormatException)
                {
                    Console.WriteLine("   Exception: Corrupted data.");
                    DisplayResourceInfo(rdr, (string)dict.Key, true);
                }
                catch (TypeLoadException)
                {
                    Console.WriteLine("   Exception: Cannot load the data type.");
                    DisplayResourceInfo(rdr, (string)dict.Key, false);
                }
            }
        }
    
        [SupportedOSPlatform("windows")]
        private static void DisplayResourceInfo(ResourceReader rr,
                                        string key, bool loaded)
        {
            string dataType = null;
            byte[] data = null;
            rr.GetResourceData(key, out dataType, out data);
    
            // Display the data type.
            Console.WriteLine("   Data Type: {0}", dataType);
            // Display the bytes that form the available data.      
            Console.Write("   Data: ");
            int lines = 0;
            foreach (var dataItem in data)
            {
                lines++;
                Console.Write("{0:X2} ", dataItem);
                if (lines % 25 == 0)
                    Console.Write("\n         ");
            }
            Console.WriteLine();
            // Try to recreate current state of data.
            // Do: Bitmap, DateTimeTZI
            switch (dataType)
            {
                // Handle internally serialized string data (ResourceTypeCode members).
                case "ResourceTypeCode.String":
                    BinaryReader reader = new BinaryReader(new MemoryStream(data));
                    string binData = reader.ReadString();
                    Console.WriteLine("   Recreated Value: {0}", binData);
                    break;
                case "ResourceTypeCode.Int32":
                    Console.WriteLine("   Recreated Value: {0}",
                                      BitConverter.ToInt32(data, 0));
                    break;
                case "ResourceTypeCode.Boolean":
                    Console.WriteLine("   Recreated Value: {0}",
                                      BitConverter.ToBoolean(data, 0));
                    break;
                // .jpeg image stored as a stream.
                case "ResourceTypeCode.Stream":
                    const int OFFSET = 4;
                    int size = BitConverter.ToInt32(data, 0);
                    Bitmap value1 = new Bitmap(new MemoryStream(data, OFFSET, size));
                    Console.WriteLine("   Recreated Value: {0}", value1);
                    break;
                default:
                    break;
            }
            Console.WriteLine();
        }
    }
    

    Nach dem Ändern des Quellcodes (z. B. durch absichtliches Auslösen eines FormatException Am Endes des try Blocks) können Sie das Beispiel ausführen, um zu sehen, wie Aufrufe GetResourceData Sie zum Abrufen oder Neustellen einiger Ressourceninformationen aktivieren.