Klasa ResourceReader zapewnia standardową implementację interfejsu IResourceReader . Wystąpienie ResourceReader reprezentuje autonomiczny plik resources lub plik resources osadzony w zestawie. Służy do wyliczania zasobów w pliku resources i pobierania par nazwa/wartość. Różni się ona od ResourceManager klasy , która jest używana do pobierania określonych nazwanych zasobów z pliku resources, który jest osadzony w zestawie. Klasa służy do pobierania ResourceManager zasobów, których nazwy są znane z wyprzedzeniem, podczas gdy ResourceReader klasa jest przydatna do pobierania zasobów, których liczba lub dokładne nazwy nie są znane w czasie kompilacji. Na przykład aplikacja może używać pliku zasobów do przechowywania informacji o konfiguracji zorganizowanych w sekcjach i elementach w sekcji, gdzie liczba sekcji lub elementów w sekcji nie jest znana z wyprzedzeniem. Następnie zasoby mogą być nazwane ogólnie (na przykład Section1, Section1Item1, Section1Item2i tak dalej) i pobierane przy użyciu ResourceReader obiektu.
Ważne
Ten typ implementuje IDisposable interfejs. Po zakończeniu korzystania z typu należy usunąć go bezpośrednio lub pośrednio. Aby usunąć typ bezpośrednio, wywołaj metodę Disposetry/catch w bloku. Aby usunąć go pośrednio, należy użyć konstrukcji języka, takiej jak using (w języku C#) lub Using (w Visual Basic). Aby uzyskać więcej informacji, zobacz sekcję "Using an Object that Implements IDisposable" (Używanie obiektu implementujące interfejs IDisposable) w dokumentacji interfejsu IDisposable .
Tworzenie wystąpienia obiektu ResourceReader
Plik resources jest plikiem binarnym, który został skompilowany z pliku tekstowego lub pliku RESX XML przez Resgen.exe (Generator plików zasobów). ResourceReader Obiekt może reprezentować autonomiczny plik resources lub plik resources, który został osadzony w zestawie.
Aby utworzyć ResourceReader wystąpienie obiektu, który odczytuje z autonomicznego pliku resources, użyj ResourceReader konstruktora klasy ze strumieniem wejściowym lub ciągiem zawierającym nazwę pliku resources. Poniższy przykład ilustruje oba podejścia. Pierwsze wystąpienie ResourceReader obiektu reprezentującego plik resources o nazwie Resources1.resources przy użyciu jego nazwy pliku. Drugie wystąpienie ResourceReader obiektu reprezentującego plik resources o nazwie Resources2.resources przy użyciu strumienia utworzonego na podstawie pliku.
C#
// 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)
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)
Wyliczanie zasobów obiektu ResourceReader
Aby wyliczyć zasoby w pliku resources, należy wywołać GetEnumerator metodę , która zwraca System.Collections.IDictionaryEnumerator obiekt. Wywołasz metodę IDictionaryEnumerator.MoveNext , aby przejść z jednego zasobu do następnego. Metoda zwraca false , gdy wszystkie zasoby w pliku resources zostały wyliczone.
Nazwę każdego zasobu można pobrać podczas iteracji System.Collections.IDictionaryEnumerator kolekcji i wywołać metodę GetResourceData w celu pobrania danych zasobu. Zalecamy takie podejście, jeśli nie znasz typu danych każdego zasobu lub jeśli poprzednie podejście zgłasza wyjątki.
Pobieranie zasobów przy użyciu właściwości IDictionaryEnumerator
Pierwsza metoda wyliczania zasobów w pliku resources obejmuje bezpośrednie pobieranie pary nazw/wartości każdego zasobu. Po wywołaniu IDictionaryEnumerator.MoveNext metody , aby przejść do każdego zasobu w kolekcji, możesz pobrać nazwę zasobu z IDictionaryEnumerator.Key właściwości i dane zasobów z IDictionaryEnumerator.Value właściwości.
W poniższym przykładzie pokazano, jak pobrać nazwę i wartość każdego zasobu w pliku resources przy użyciu właściwości IDictionaryEnumerator.Key i IDictionaryEnumerator.Value . Aby uruchomić przykład, utwórz następujący plik tekstowy o nazwie ApplicationResources.txt w celu zdefiniowania zasobów ciągów.
Następnie możesz przekonwertować plik zasobu tekstowego na plik binarny o nazwie ApplicationResources.resources przy użyciu następującego polecenia:
resgen ApplicationResources.txt
W poniższym przykładzie użyto ResourceReader klasy , aby wyliczyć każdy zasób w autonomicznym pliku zasobów binarnych i wyświetlić jego nazwę klucza i odpowiadającą mu wartość.
Jeśli FileNotFoundException nie można odnaleźć zestawu zawierającego typ, do którego należą dane.
Jeśli TypeLoadException nie można odnaleźć typu, do którego należą dane.
Zazwyczaj te wyjątki są zgłaszane, jeśli plik resources został zmodyfikowany ręcznie, jeśli zestaw, w którym zdefiniowano typ, nie został dołączony do aplikacji lub został przypadkowo usunięty lub jeśli zestaw jest starszą wersją, która poprzedza typ. Jeśli zostanie zgłoszony jeden z tych wyjątków, możesz pobrać zasoby, wyliczając każdy zasób i wywołując metodę GetResourceData , jak pokazano w poniższej sekcji. Takie podejście zapewnia pewne informacje o typie danych, które IDictionaryEnumerator.Value właściwość próbowała zwrócić.
Pobieranie zasobów według nazwy za pomocą polecenia GetResourceData
Drugie podejście do wyliczania zasobów w pliku resources obejmuje również nawigowanie po zasobach w pliku przez wywołanie IDictionaryEnumerator.MoveNext metody . Dla każdego zasobu pobierasz nazwę zasobu z IDictionaryEnumerator.Key właściwości , która jest następnie przekazywana do GetResourceData(String, String, Byte[]) metody w celu pobrania danych zasobu. Jest to zwracane jako tablica bajtów w argumencie resourceData .
Takie podejście jest bardziej niezręczne niż pobieranie nazwy i wartości zasobu z IDictionaryEnumerator.Key właściwości i IDictionaryEnumerator.Value , ponieważ zwraca rzeczywiste bajty, które tworzą wartość zasobu. Jeśli jednak próba pobrania zasobu zgłosi wyjątek, GetResourceData metoda może pomóc zidentyfikować źródło wyjątku, podając informacje o typie danych zasobu. Aby uzyskać więcej informacji o ciągu wskazującym typ danych zasobu, zobacz GetResourceData.
Poniższy przykład ilustruje sposób użycia tego podejścia do pobierania zasobów i obsługi wszelkich zgłaszanych wyjątków. Programowo tworzy binarny plik resources zawierający cztery ciągi, jedną wartość logiczną, jedną liczbę całkowitą i jedną mapę bitową. Aby uruchomić przykład, wykonaj następujące czynności:
Skompiluj i wykonaj następujący kod źródłowy, który tworzy plik resources o nazwie ContactResources.resources.
C#
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Resources;
using System.Runtime.Versioning;
publicclassExample5
{
[SupportedOSPlatform("windows")]
publicstaticvoidRun()
{
// 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();
}
}
}
Plik kodu źródłowego nosi nazwę CreateResources.cs. Można go skompilować w języku C#, używając następującego polecenia:
csc CreateResources.cs /r:library.dll
Skompiluj i uruchom następujący kod, aby wyliczyć zasoby w pliku ContactResources.resources.
C#
using System;
using System.Collections;
using System.Drawing;
using System.IO;
using System.Resources;
using System.Runtime.Versioning;
publicclassExample6
{
[SupportedOSPlatform("windows")]
publicstaticvoidRun()
{
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")]
privatestaticvoidDisplayResourceInfo(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, DateTimeTZIswitch (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":
constint 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();
}
}
Po zmodyfikowaniu kodu źródłowego (na przykład przez celowe zgłoszenie FormatException elementu na końcu try bloku) możesz uruchomić przykład, aby zobaczyć, jak wywołania GetResourceData umożliwiają pobieranie lub ponowne tworzenie informacji o zasobie.
Współpracuj z nami w serwisie GitHub
Źródło tej zawartości można znaleźć w witrynie GitHub, gdzie można również tworzyć i przeglądać problemy i żądania ściągnięcia. Więcej informacji znajdziesz w naszym przewodniku dla współtwórców.
Opinia o produkcie .NET
.NET to projekt typu open source. Wybierz link, aby przekazać opinię:
Dowiedz się, jak używać statycznych i dynamicznych zasobów udostępnionych do tworzenia interfejsu użytkownika maUI. Zobacz też, jak style mogą sprawić, że interfejs użytkownika będzie spójny i dostępny.