Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tento článek obsahuje doplňující poznámky k referenční dokumentaci pro toto rozhraní API.
Důležité
Volání metod z této třídy s nedůvěryhodnými daty představuje bezpečnostní riziko. Volejte metody z této třídy pouze s důvěryhodnými daty. Další informace naleznete v tématu Ověření všech vstupů.
Třída ResourceReader poskytuje standardní implementaci IResourceReader rozhraní. Instance ResourceReader představuje samostatný soubor .resources nebo soubor .resources, který je vložen do sestavení. Slouží k vytvoření výčtu prostředků v souboru .resources a načtení párů název/hodnota. Liší se od třídy ResourceManager, která se používá k načtení zadaných pojmenovaných prostředků ze souboru .resources, který je vložen do sestavení. Třída ResourceManager slouží k načtení prostředků, jejichž názvy jsou známy předem, zatímco ResourceReader třída je užitečná pro načtení prostředků, jejichž počet nebo přesné názvy nejsou známy v době kompilace. Aplikace může například použít soubor prostředků k ukládání konfiguračních informací uspořádaných do oddílů a položek v oddílu, kde počet oddílů nebo položek v oddílu není předem znám. Prostředky lze pak pojmenovat obecně (například Section1, Section1Item1, Section1Item2, atd.) a poté načíst pomocí objektu ResourceReader.
Důležité
Tento typ implementuje rozhraní IDisposable. Jakmile skončíte s používáním typu, měli byste ho odstranit buď přímo, nebo nepřímo. Chcete-li typ odstranit přímo, zavolejte jeho Dispose metodu v bloku try/catch. Pokud ho chcete zlikvidovat nepřímo, použijte konstruktor jazyka, jako je using (v jazyce C#) nebo Using (v jazyce Visual Basic). Další informace najdete v části Použití objektu, který implementuje IDisposable v dokumentaci k rozhraní IDisposable.
Vytvoření instance objektu ResourceReader
Soubor .resources je binární soubor zkompilovaný z textového nebo XML .resx souboru pomocí Resgen.exe (Generátor souborů prostředků). Objekt ResourceReader může představovat samostatný soubor .resources nebo soubor .resources, který byl vložen do sestavení.
Chcete-li vytvořit instanci objektu ResourceReader, který čte ze samostatného souboru .resources, použijte konstruktor třídy ResourceReader se vstupním datovým proudem nebo řetězcem, který obsahuje název souboru .resources. Následující příklad ukazuje oba přístupy. První vytvoří instanci objektu ResourceReader, který představuje soubor .resources s názvem Resources1.resources pomocí názvu souboru. Druhý vytvoří instanci objektu ResourceReader, který představuje soubor .resources s názvem Resources2.resources pomocí datového proudu vytvořeného ze souboru.
// 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)
Chcete-li vytvořit ResourceReader objekt, který představuje vložený soubor .resources, vytvořte instanci objektu Assembly ze sestavení, ve kterém je vložen soubor .resources. Jeho Assembly.GetManifestResourceStream metoda vrátí Stream objekt, který lze předat ResourceReader(Stream) konstruktoru. Následující příklad inicializuje instanci objektu ResourceReader, který představuje vložený soubor .resources.
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)
Vytvoření výčtu prostředků objektu ResourceReader
Chcete-li vytvořit výčet prostředků v souboru .resources, zavoláte metodou GetEnumerator, která vrátí System.Collections.IDictionaryEnumerator objekt. Zavoláte metodu IDictionaryEnumerator.MoveNext, abyste se přesunuli z jednoho prostředku na následující. Metoda vrátí false, když byly všechny prostředky v souboru .resources vyčerpány.
Poznámka:
Ačkoli třída ResourceReader implementuje rozhraní IEnumerable a metodu IEnumerable.GetEnumerator, metoda ResourceReader.GetEnumerator neposkytuje implementaci IEnumerable.GetEnumerator. Místo toho metoda ResourceReader.GetEnumerator vrátí objekt rozhraní IDictionaryEnumerator, který poskytuje přístup ke dvojici názvů a hodnot jednotlivých prostředků.
Jednotlivé prostředky z kolekce můžete získat dvěma způsoby:
Každý prostředek v kolekci System.Collections.IDictionaryEnumerator můžete iterovat a pomocí vlastností System.Collections.IDictionaryEnumerator načíst název a hodnotu prostředku. Tuto techniku doporučujeme, když jsou všechny prostředky stejného typu nebo znáte datový typ každého prostředku.
Název každého prostředku můžete načíst při iteraci kolekce System.Collections.IDictionaryEnumerator a voláním metody GetResourceData načíst data prostředku. Tento přístup doporučujeme, když neznáte datový typ každého prostředku nebo pokud předchozí přístup vyvolá výjimky.
Načítání prostředků pomocí vlastností IDictionaryEnumerator
První metoda vytvoření výčtu prostředků v souboru .resources zahrnuje přímé načtení dvojice název/hodnota každého prostředku. Jakmile zavoláte metodu IDictionaryEnumerator.MoveNext, která se má přesunout k jednotlivým prostředkům v kolekci, můžete název prostředku načíst z vlastnosti IDictionaryEnumerator.Key a dat o prostředcích z vlastnosti IDictionaryEnumerator.Value.
Následující příklad ukazuje, jak načíst název a hodnotu každého prostředku v souboru .resources pomocí vlastností IDictionaryEnumerator.Key a IDictionaryEnumerator.Value. Pokud chcete spustit příklad, vytvořte následující textový soubor s názvem ApplicationResources.txt, který definuje prostředky řetězců.
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:"
Potom můžete textový soubor prostředků převést na binární soubor nazvaný ApplicationResources.resources pomocí následujícího příkazu:
resgen ApplicationResources.txt
Následující příklad pak použije ResourceReader třídu k vytvoření výčtu jednotlivých prostředků v samostatném binárním souboru .resources a k zobrazení názvu klíče a odpovídající hodnoty.
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)
Pokus o načtení dat zdrojů z vlastnosti IDictionaryEnumerator.Value může vyvolat následující výjimky:
- FormatException, pokud data nejsou v očekávaném formátu.
- FileNotFoundException, pokud sestavení obsahující typ, do kterého data patří, nelze najít.
- TypeLoadException, pokud nelze nalézt typ, do kterého data patří.
Tyto výjimky jsou obvykle vyvolány v případě, že byl soubor .resources upraven ručně, pokud sestavení, ve kterém je definován typ, buď není součástí aplikace, nebo byla neúmyslně odstraněna, nebo pokud je sestavení starší verzí, která předchází typu. Pokud je vyvolána jedna z těchto výjimek, můžete načíst prostředky výčtem jednotlivých prostředků a voláním metody GetResourceData, jak ukazuje následující oddíl. Tento přístup vám poskytuje nějaké informace o datovém typu, který se vlastnost IDictionaryEnumerator.Value pokusila vrátit.
Načtení prostředků podle názvu pomocí GetResourceData
Druhý přístup k vytvoření výčtu prostředků v souboru .resources zahrnuje také procházení prostředků v souboru voláním metody IDictionaryEnumerator.MoveNext. Pro každý prostředek načtete název prostředku z vlastnosti IDictionaryEnumerator.Key, která se pak předá metodě GetResourceData(String, String, Byte[]) pro načtení dat prostředku. Vrátí se jako pole bajtů v argumentu resourceData.
Tento přístup je složitější než načtení názvu a hodnoty prostředku z vlastností IDictionaryEnumerator.Key a IDictionaryEnumerator.Value, protože vrací skutečné bajty, které tvoří hodnotu prostředku. Pokud však pokus o načtení prostředku vyvolá výjimku, může metoda GetResourceData pomoct identifikovat zdroj výjimky poskytnutím informací o datovém typu prostředku. Další informace o řetězci, který označuje datový typ prostředku, najdete v tématu GetResourceData.
Následující příklad ukazuje, jak pomocí tohoto přístupu načíst prostředky a zpracovat jakékoli výjimky, které mohou být vyvolány. Programově vytvoří binární soubor .resources, který obsahuje čtyři řetězce, jednu logickou hodnotu, jedno celé číslo a jeden rastrový obrázek. Pokud chcete spustit příklad, postupujte takto:
Zkompilujte a spusťte následující zdrojový kód, který vytvoří soubor .resources s názvem 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(); } } }Soubor zdrojového kódu má název CreateResources.cs. V jazyce C# ho můžete zkompilovat pomocí následujícího příkazu:
csc CreateResources.cs /r:library.dllZkompilujte a spusťte následující kód pro vytvoření výčtu prostředků v souboru 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(); } }Po úpravě zdrojového kódu (například záměrně vyvoláním FormatException na konci bloku
try) můžete spustit příklad a podívat se, jak volání GetResourceData umožňují načíst nebo znovu vytvořit některé informace o prostředku.