System.Resources.ResourceReader-klass

Anmärkning

Den här artikeln innehåller ytterligare kommentarer till referensdokumentationen för det här API:et.

Viktigt!

Att anropa metoder från den här klassen med ej betrodda data är en säkerhetsrisk. Anropa metoderna från den här klassen endast med betrodda data. För mer information, se Verifiera alla indata.

Klassen ResourceReader tillhandahåller en standardimplementering av IResourceReader gränssnittet. En ResourceReader instans representerar antingen en fristående .resources-fil eller en .resources-fil som är inbäddad i en sammansättning. Den används för att räkna upp resurserna i en .resources-fil och hämta dess namn/värde-par. Den skiljer sig från ResourceManager klassen, som används för att hämta angivna namngivna resurser från en .resources-fil som är inbäddad i en sammansättning. Klassen ResourceManager används för att hämta resurser vars namn är kända i förväg, medan ResourceReader klassen är användbar för att hämta resurser vars antal eller exakta namn inte är kända vid kompileringstiden. Ett program kan till exempel använda en resursfil för att lagra konfigurationsinformation som är organiserad i avsnitt och objekt i ett avsnitt, där antalet avsnitt eller objekt i ett avsnitt inte är känt i förväg. Resurser kan sedan namnges allmänt (till exempel Section1, Section1Item1, Section1Item2och så vidare) och hämtas med hjälp av ett ResourceReader -objekt.

Viktigt!

Den här typen implementerar IDisposable gränssnittet. När du har använt typen bör du kassera den på ett direkt eller indirekt sätt. Om du vill ta bort typen direkt anropar du dess Dispose metod i ett try/catch block. Om du vill ta bort det indirekt använder du en språkkonstruktion som using (i C#) eller Using (i Visual Basic). Mer information finns i avsnittet "Använda ett objekt som implementerar IDisposable" i gränssnittsdokumentationen IDisposable .

Instansiera ett ResourceReader-objekt

En .resources-fil är en binär fil som har kompilerats från antingen en textfil eller en XML.resx-fil av Resgen.exe (Resursfilgenerator). Ett ResourceReader objekt kan representera antingen en fristående .resources-fil eller en .resources-fil som har bäddats in i en sammansättning.

Om du vill instansiera ett ResourceReader objekt som läser från en fristående .resources-fil använder du ResourceReader klasskonstruktorn med antingen en indataström eller en sträng som innehåller filnamnet .resources. I följande exempel visas båda metoderna. Den första instansierar ett ResourceReader objekt som representerar en .resources-fil med namnet Resources1.resources med hjälp av dess filnamn. Den andra instansierar ett ResourceReader objekt som representerar en .resources-fil med namnet Resources2.resources med hjälp av en ström som skapats från filen.

// 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)

Om du vill skapa ett ResourceReader objekt som representerar en inbäddad .resources-fil instansierar du ett Assembly objekt från sammansättningen där .resources-filen är inbäddad. Metoden Assembly.GetManifestResourceStream returnerar ett Stream objekt som kan skickas till ResourceReader(Stream) konstruktorn. I följande exempel instansieras ett ResourceReader objekt som representerar en inbäddad .resources-fil.

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)

Räkna upp resurser för ett ResourceReader-objekt

Om du vill räkna upp resurserna i en .resources-fil anropar GetEnumerator du metoden som returnerar ett System.Collections.IDictionaryEnumerator objekt. Du anropar IDictionaryEnumerator.MoveNext metoden för att flytta från en resurs till en annan. Metoden returnerar false när alla resurser i .resources-filen har räknats upp.

Anmärkning

ResourceReader Även om klassen implementerar IEnumerable gränssnittet och IEnumerable.GetEnumerator metoden tillhandahåller ResourceReader.GetEnumerator metoden inte implementeringenIEnumerable.GetEnumerator. ResourceReader.GetEnumerator I stället returnerar metoden ett IDictionaryEnumerator gränssnittsobjekt som ger åtkomst till varje resurs namn/värde-par.

Du kan hämta de enskilda resurserna i samlingen på två sätt:

Hämta resurser med hjälp av IDictionaryEnumerator-egenskaper

Den första metoden för att räkna upp resurserna i en .resources-fil är att hämta varje resurss namn/värde-par direkt. När du anropar IDictionaryEnumerator.MoveNext metoden för att flytta till varje resurs i samlingen kan du hämta resursnamnet från IDictionaryEnumerator.Key egenskapen och resursdata från IDictionaryEnumerator.Value egenskapen.

I följande exempel visas hur du hämtar namnet och värdet för varje resurs i en .resources-fil med hjälp av egenskaperna IDictionaryEnumerator.Key och IDictionaryEnumerator.Value. Om du vill köra exemplet skapar du följande textfil med namnet ApplicationResources.txt för att definiera strängresurser.

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:"

Du kan sedan konvertera textresursfilen till en binär fil med namnet ApplicationResources.resources med hjälp av följande kommando:

resgen ApplicationResources.txt

I följande exempel används ResourceReader sedan klassen för att räkna upp varje resurs i den fristående binära .resources-filen och för att visa dess nyckelnamn och motsvarande värde.

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($"   {dict.Key}: '{dict.Value}' (Type {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)

Försöket att hämta resursdata från IDictionaryEnumerator.Value egenskapen kan utlösa följande undantag:

Dessa undantag utlöses vanligtvis om .resources-filen har ändrats manuellt, om sammansättningen där en typ har definierats antingen inte har inkluderats i ett program eller har tagits bort oavsiktligt eller om sammansättningen är en äldre version som föregår en typ. Om ett av dessa undantag utlöses kan du hämta resurser genom att räkna upp varje resurs och anropa GetResourceData metoden, vilket visas i följande avsnitt. Den här metoden ger dig viss information om den datatyp som IDictionaryEnumerator.Value egenskapen försökte returnera.

Hämta resurser efter namn med GetResourceData

Den andra metoden för att räkna upp resurser i en .resources-fil innebär också att navigera genom resurserna i filen genom att anropa IDictionaryEnumerator.MoveNext metoden. För varje resurs hämtar du resursens namn från IDictionaryEnumerator.Key egenskapen, som sedan skickas till GetResourceData(String, String, Byte[]) metoden för att hämta resursens data. Detta returneras som en bytematris i resourceData argumentet.

Den här metoden är mer besvärlig än att hämta resursnamnet och värdet från IDictionaryEnumerator.Key egenskaperna och IDictionaryEnumerator.Value eftersom den returnerar de faktiska byte som utgör resursvärdet. Men om försöket att hämta resursen genererar ett undantag GetResourceData kan metoden hjälpa till att identifiera källan till undantaget genom att ange information om resursens datatyp. Mer information om strängen som anger resursens datatyp finns i GetResourceData.

I följande exempel visas hur du använder den här metoden för att hämta resurser och hantera eventuella undantag som genereras. Programmässigt skapar den en binär .resources-fil som innehåller fyra strängar, en boolesk, ett heltal och en bitmapp. Kör exemplet genom att göra följande:

  1. Kompilera och kör följande källkod, som skapar en .resources-fil med namnet ContactResources.resources.

    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();
            }
        }
    }
    

    Källkodsfilen heter CreateResources.cs. Du kan kompilera den i C# med hjälp av följande kommando:

    csc CreateResources.cs /r:library.dll
    
  2. Kompilera och kör följande kod för att räkna upp resurserna i filen ContactResources.resources.

    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: {dict.Key}");
                try
                {
                    Console.WriteLine($"   Value: {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: {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: {binData}");
                    break;
                case "ResourceTypeCode.Int32":
                    Console.WriteLine($"   Recreated Value: {BitConverter.ToInt32(data, 0)}");
                    break;
                case "ResourceTypeCode.Boolean":
                    Console.WriteLine($"   Recreated Value: {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: {value1}");
                    break;
                default:
                    break;
            }
            Console.WriteLine();
        }
    }
    

    När du har modifierat källkoden (till exempel genom att avsiktligt kasta en FormatException i slutet av try blocket) kan du köra exemplet för att se hur anrop gör att GetResourceData du kan hämta eller återskapa viss resursinformation.