Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
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:
Du kan iterera varje resurs i System.Collections.IDictionaryEnumerator samlingen och använda System.Collections.IDictionaryEnumerator egenskaper för att hämta resursnamnet och värdet. Vi rekommenderar den här tekniken när alla resurser är av samma typ, eller om du känner till datatypen för varje resurs.
Du kan hämta namnet på varje resurs när du itererar System.Collections.IDictionaryEnumerator samlingen och anropa GetResourceData metoden för att hämta resursens data. Vi rekommenderar den här metoden när du inte känner till datatypen för varje resurs eller om den tidigare metoden utlöser undantag.
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:
- A FormatException om data inte är i förväntat format.
- En FileNotFoundException om sammansättningen som innehåller den typ som data tillhör inte kan hittas.
- En TypeLoadException om det inte går att hitta den typ som data tillhör.
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:
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.dllKompilera 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
tryblocket) kan du köra exemplet för att se hur anrop gör att GetResourceData du kan hämta eller återskapa viss resursinformation.