System.Resources.ResourceManager, klasa

Ten artykuł zawiera dodatkowe uwagi dotyczące dokumentacji referencyjnej dla tego interfejsu API.

Ważne

Wywoływanie metod z tej klasy z niezaufanymi danymi jest zagrożeniem bezpieczeństwa. Wywołaj metody z tej klasy tylko z zaufanymi danymi. Aby uzyskać więcej informacji, zobacz Validate All Inputs (Weryfikowanie wszystkich danych wejściowych).

Klasa ResourceManager pobiera zasoby z binarnego pliku resources osadzonego w zestawie lub z autonomicznego pliku resources. Jeśli aplikacja została zlokalizowana i zlokalizowane zasoby zostały wdrożone w zestawach satelitarnych, wyszukuje zasoby specyficzne dla kultury, zapewnia rezerwę zasobów, gdy zlokalizowany zasób nie istnieje i obsługuje serializacji zasobów.

Aplikacje klasyczne

W przypadku aplikacji ResourceManager klasycznych klasa pobiera zasoby z plików zasobów binarnych (.resources). Zazwyczaj kompilator języka lub konsolidator zestawów (AL.exe) osadza te pliki zasobów w zestawie. Za pomocą ResourceManager obiektu można również pobrać zasoby bezpośrednio z pliku resources, który nie jest osadzony w zestawie, wywołując metodę CreateFileBasedResourceManager .

Uwaga

Używanie autonomicznych plików resources w aplikacji ASP.NET spowoduje przerwanie wdrażania programu XCOPY, ponieważ zasoby pozostają zablokowane do momentu jawnego zwolnienia ich przez metodę ReleaseAllResources . Jeśli chcesz wdrożyć zasoby przy użyciu aplikacji ASP.NET, skompiluj pliki resources do zestawów satelickich.

W aplikacji opartej na zasobach jeden plik resources zawiera zasoby kultury domyślnej, której zasoby są używane, jeśli nie można znaleźć zasobów specyficznych dla kultury. Jeśli na przykład domyślna kultura aplikacji to angielski (en), zasoby języka angielskiego są używane zawsze, gdy nie można odnaleźć zlokalizowanych zasobów dla określonej kultury, takiej jak angielski (Stany Zjednoczone) (en-US) lub francuski (fr-FR). Zazwyczaj zasoby dla kultury domyślnej są osadzone w głównym zestawie aplikacji, a zasoby dla innych zlokalizowanych kultur są osadzone w zestawach satelitarnych. Zestawy satelitarne zawierają tylko zasoby. Mają one taką samą nazwę pliku głównego jak główny zestaw i rozszerzenie .resources.dll. W przypadku aplikacji, których zestawy nie są zarejestrowane w globalnej pamięci podręcznej zestawów zestawów, zestawy satelitarne są przechowywane w podkatalogu aplikacji, którego nazwa odpowiada kulturze zestawu.

Tworzenie zasobów

Podczas tworzenia aplikacji opartej na zasobach informacje o zasobach są przechowywane w plikach tekstowych (plikach z rozszerzeniem .txt lub restext) lub plikach XML (plikach z rozszerzeniem resx). Następnie skompilujesz pliki tekstowe lub XML za pomocą generatora plików zasobów (Resgen.exe), aby utworzyć binarny plik resources. Następnie można osadzić wynikowy plik resources w pliku wykonywalnym lub bibliotece przy użyciu opcji kompilatora, takiej jak /resources kompilatory języka C# i Visual Basic, lub osadzić go w zestawie satelitarnym przy użyciu konsolidatora zestawów (AI.exe).. Jeśli do projektu programu Visual Studio dołączysz plik resx, program Visual Studio automatycznie obsługuje kompilację i osadzanie domyślnych i zlokalizowanych zasobów w ramach procesu kompilacji.

W idealnym przypadku należy utworzyć zasoby dla każdego języka obsługiwanego przez aplikację lub co najmniej dla znaczącego podzbioru każdego języka. Nazwy plików binarnych .resources są zgodne z konwencją nazewnictwa basename.cultureName.resources, gdzie basename jest nazwą aplikacji lub nazwą klasy, w zależności od żądanego poziomu szczegółów. Właściwość jest używana do określania CultureInfo.Namewartości cultureName. Zasób domyślnej kultury aplikacji powinien mieć nazwę basename.resources.

Załóżmy na przykład, że zestaw zawiera kilka zasobów w pliku zasobów o nazwie podstawowej MyResources. Te pliki zasobów powinny mieć nazwy, takie jak MyResources.ja-JP.resources dla kultury Japonii (japoński), MyResources.de.resources dla kultury niemieckiej, MyResources.zh-CHS.resources dla uproszczonej chińskiej kultury i MyResources.fr-BE.resources dla kultury francuskiej (Belgia). Domyślny plik zasobu powinien mieć nazwę MyResources.resources. Pliki zasobów specyficzne dla kultury są często pakowane w zestawy satelitarne dla każdej kultury. Domyślny plik zasobu powinien być osadzony w głównym zestawie aplikacji.

Należy pamiętać, że konsolidator zestawów umożliwia oznaczenie zasobów jako prywatnych, ale zawsze należy oznaczyć je jako publiczne, aby można było uzyskać do nich dostęp przez inne zestawy. (Ponieważ zestaw satelitarny nie zawiera kodu, zasoby oznaczone jako prywatne są niedostępne dla aplikacji za pośrednictwem dowolnego mechanizmu).

Aby uzyskać więcej informacji na temat tworzenia, pakowania i wdrażania zasobów, zobacz artykuły Tworzenie plików zasobów, Tworzenie zestawów satelickich oraz Pakowanie i wdrażanie zasobów.

Tworzenie wystąpienia obiektu ResourceManager

Utworzenie wystąpienia ResourceManager obiektu, który pobiera zasoby z osadzonego pliku resources przez wywołanie jednego z przeciążeń konstruktora klasy. Ściśle łączy ResourceManager obiekt z określonym plikiem resources i skojarzonymi zlokalizowanymi plikami resources w zestawach satelitarnych.

Dwa najczęściej nazywane konstruktorami to:

  • ResourceManager(String, Assembly) wyszukuje zasoby na podstawie dwóch podanych informacji: podstawowej nazwy pliku resources i zestawu, w którym znajduje się domyślny plik resources. Nazwa podstawowa zawiera przestrzeń nazw i nazwę główną pliku resources bez jego kultury lub rozszerzenia. Należy pamiętać, że pliki resources skompilowane z wiersza polecenia zwykle nie zawierają nazwy przestrzeni nazw, natomiast pliki resources utworzone w środowisku programu Visual Studio. Jeśli na przykład plik zasobu nosi nazwę MyCompany.StringResources.resources, a ResourceManager konstruktor jest wywoływany z metody statycznej o nazwie Example.Main, następujący kod tworzy wystąpienie ResourceManager obiektu, który może pobrać zasoby z pliku resources:

    ResourceManager rm = new ResourceManager("MyCompany.StringResources",
                                             typeof(Example).Assembly);
    
    Dim rm As New ResourceManager("MyCompany.StringResources",
                                GetType(Example2).Assembly)
    
  • ResourceManager(Type) wyszukuje zasoby w zestawach satelickich na podstawie informacji z obiektu typu. W pełni kwalifikowana nazwa typu odpowiada podstawowej nazwie pliku resources bez rozszerzenia nazwy pliku. W aplikacjach klasycznych tworzonych przy użyciu Projektant zasobów programu Visual Studio program Visual Studio tworzy klasę otoki, której w pełni kwalifikowana nazwa jest taka sama jak nazwa główna pliku resources. Jeśli na przykład plik zasobu nosi nazwę MyCompany.StringResources.resources i istnieje klasa otoki o nazwie MyCompany.StringResources, następujący kod tworzy wystąpienie ResourceManager obiektu, który może pobrać zasoby z pliku resources:

    ResourceManager rm = new ResourceManager(typeof(MyCompany.StringResources));
    
    Dim rm As New ResourceManager(GetType(MyCompany.StringResources))
    

Jeśli nie można odnaleźć odpowiednich zasobów, wywołanie konstruktora tworzy prawidłowy ResourceManager obiekt. Jednak próba pobrania zasobu zgłasza MissingManifestResourceException wyjątek. Aby uzyskać informacje na temat obsługi wyjątku, zobacz sekcję Handle MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions (Wyjątki wyjątków Handle MissingManifestResourceException i MissingSatelliteAssemblyException) w dalszej części tego artykułu.

W poniższym przykładzie pokazano, jak utworzyć ResourceManager wystąpienie obiektu. Zawiera kod źródłowy pliku wykonywalnego o nazwie ShowTime.exe. Zawiera również następujący plik tekstowy o nazwie Strings.txt zawierający jeden zasób ciągu: TimeHeader

TimeHeader=The current time is

Możesz użyć pliku wsadowego, aby wygenerować plik zasobu i osadzić go w pliku wykonywalnym. Oto plik wsadowy do wygenerowania pliku wykonywalnego przy użyciu kompilatora języka C#:

resgen strings.txt
csc ShowTime.cs /resource:strings.resources

W przypadku kompilatora języka Visual Basic można użyć następującego pliku wsadowego:

resgen strings.txt
vbc ShowTime.vb /resource:strings.resources
using System;
using System.Resources;

public class ShowTimeEx
{
    public static void Main()
    {
        ResourceManager rm = new ResourceManager("Strings",
                                 typeof(Example).Assembly);
        string timeString = rm.GetString("TimeHeader");
        Console.WriteLine("{0} {1:T}", timeString, DateTime.Now);
    }
}
// The example displays output like the following:
//        The current time is 2:03:14 PM
Imports System.Resources

Module Example6
    Public Sub Main()
        Dim rm As New ResourceManager("Strings", GetType(Example6).Assembly)
        Dim timeString As String = rm.GetString("TimeHeader")
        Console.WriteLine("{0} {1:T}", timeString, Date.Now)
    End Sub
End Module
' The example displays output similar to the following:
'       The current time is 2:03:14 PM

ResourceManager i zasoby specyficzne dla kultury

Zlokalizowana aplikacja wymaga wdrożenia zasobów, zgodnie z opisem w artykule Pakowanie i wdrażanie zasobów. Jeśli zestawy są prawidłowo skonfigurowane, menedżer zasobów określa, które zasoby mają być pobierane na podstawie właściwości bieżącego wątku Thread.CurrentUICulture . (Ta właściwość zwraca również kulturę interfejsu użytkownika bieżącego wątku). Jeśli na przykład aplikacja jest kompilowana z domyślnymi zasobami języka angielskiego w głównym zestawie oraz z zasobami języka francuskiego i rosyjskiego w dwóch zestawach satelickich, a Thread.CurrentUICulture właściwość jest ustawiona na fr-FR, menedżer zasobów pobiera zasoby francuskie.

Właściwość można ustawić CurrentUICulture jawnie lub niejawnie. Sposób ustawiania określa sposób pobierania ResourceManager zasobów przez obiekt na podstawie kultury:

  • Jeśli jawnie ustawisz Thread.CurrentUICulture właściwość na określoną kulturę, menedżer zasobów zawsze pobiera zasoby dla tej kultury, niezależnie od przeglądarki użytkownika lub języka systemu operacyjnego. Rozważmy aplikację skompilowana przy użyciu domyślnych zasobów języka angielskiego i trzech zestawów satelickich, które zawierają zasoby dla języka angielskiego (Stany Zjednoczone), francuskiego (Francja) i rosyjskiego (Rosja). CurrentUICulture Jeśli właściwość jest ustawiona na fr-FR, ResourceManager obiekt zawsze pobiera zasoby francuskie (Francja), nawet jeśli język systemu operacyjnego użytkownika nie jest francuski. Przed jawnym ustawieniem właściwości upewnij się, że jest to pożądane zachowanie.

    W aplikacjach ASP.NET należy jawnie ustawić Thread.CurrentUICulture właściwość, ponieważ jest mało prawdopodobne, aby ustawienie na serwerze było zgodne z przychodzącymi żądaniami klientów. Aplikacja ASP.NET może jawnie ustawić Thread.CurrentUICulture właściwość na język akceptowania przeglądarki użytkownika.

    Jawne ustawienie Thread.CurrentUICulture właściwości definiuje bieżącą kulturę interfejsu użytkownika dla tego wątku. Nie ma to wpływu na bieżącą kulturę interfejsu użytkownika innych wątków w aplikacji.

  • Kulturę interfejsu użytkownika wszystkich wątków w domenie aplikacji można ustawić, przypisując obiekt reprezentujący kulturę CultureInfo statyczną CultureInfo.DefaultThreadCurrentUICulture .

  • Jeśli nie ustawisz jawnie bieżącej kultury interfejsu użytkownika i nie zdefiniujesz domyślnej kultury dla bieżącej domeny aplikacji, CultureInfo.CurrentUICulture właściwość jest ustawiana niejawnie przez funkcję systemu Windows GetUserDefaultUILanguage . Ta funkcja jest udostępniana przez wielojęzyczny interfejs użytkownika (MUI), która umożliwia użytkownikowi ustawienie języka domyślnego. Jeśli język interfejsu użytkownika nie jest ustawiony przez użytkownika, domyślnie jest to język zainstalowany przez system, czyli język zasobów systemu operacyjnego.

Poniższy prosty przykład "Hello world" jawnie ustawia bieżącą kulturę interfejsu użytkownika. Zawiera zasoby dla trzech kultur: angielski (Stany Zjednoczone) lub en-US, francuski (Francja) lub fr-FR oraz rosyjski (Rosja) lub ru-RU. Zasoby en-US znajdują się w pliku tekstowym o nazwie Greetings.txt:

HelloString=Hello world!

Zasoby fr-FR znajdują się w pliku tekstowym o nazwie Greetings.fr-FR.txt:

HelloString=Salut tout le monde!

Zasoby ru-RU znajdują się w pliku tekstowym o nazwie Greetings.ru-RU.txt:

HelloString=Всем привет!

Oto kod źródłowy przykładu (Example.vb dla wersji Visual Basic lub Example.cs dla wersji języka C#):

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

public class Example
{
    public static void Main()
    {
        // Create array of supported cultures
        string[] cultures = { "en-CA", "en-US", "fr-FR", "ru-RU" };
        Random rnd = new Random();
        int cultureNdx = rnd.Next(0, cultures.Length);
        CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture;
        ResourceManager rm = new ResourceManager("Greetings", typeof(Example).Assembly);
        try
        {
            CultureInfo newCulture = new CultureInfo(cultures[cultureNdx]);
            Thread.CurrentThread.CurrentCulture = newCulture;
            Thread.CurrentThread.CurrentUICulture = newCulture;
            string greeting = String.Format("The current culture is {0}.\n{1}",
                                            Thread.CurrentThread.CurrentUICulture.Name,
                                            rm.GetString("HelloString"));
            Console.WriteLine(greeting);
        }
        catch (CultureNotFoundException e)
        {
            Console.WriteLine("Unable to instantiate culture {0}", e.InvalidCultureName);
        }
        finally
        {
            Thread.CurrentThread.CurrentCulture = originalCulture;
            Thread.CurrentThread.CurrentUICulture = originalCulture;
        }
    }
}
// The example displays output like the following:
//       The current culture is ru-RU.
//       Всем привет!
Imports System.Globalization
Imports System.Resources
Imports System.Threading

Module Example
   Sub Main()
      ' Create array of supported cultures
      Dim cultures() As String = {"en-CA", "en-US", "fr-FR", "ru-RU" }
      Dim rnd As New Random()
      Dim cultureNdx As Integer = rnd.Next(0, cultures.Length)
      Dim originalCulture As CultureInfo = Thread.CurrentThread.CurrentCulture
      Dim rm As New ResourceManager("Greetings", GetType(Example).Assembly)
      Try
         Dim newCulture As New CultureInfo(cultures(cultureNdx))
         Thread.CurrentThread.CurrentCulture = newCulture
         Thread.CurrentThread.CurrentUICulture = newCulture
         Dim greeting As String = String.Format("The current culture is {0}.{1}{2}",
                                                Thread.CurrentThread.CurrentUICulture.Name,
                                                vbCrLf, rm.GetString("HelloString"))

         Console.WriteLine(greeting)
      Catch e As CultureNotFoundException
         Console.WriteLine("Unable to instantiate culture {0}", e.InvalidCultureName)
      Finally
         Thread.CurrentThread.CurrentCulture = originalCulture
         Thread.CurrentThread.CurrentUICulture = originalCulture
      End Try
   End Sub
End Module
' The example displays output like the following:
'       The current culture is ru-RU.
'       Всем привет!

Aby skompilować ten przykład, utwórz plik wsadowy (.bat), który zawiera następujące polecenia i uruchom go z poziomu wiersza polecenia. Jeśli używasz języka C#, określ csc zamiast vbc i Example.cs zamiast Example.vb.

resgen Greetings.txt
vbc Example.vb /resource:Greetings.resources

resgen Greetings.fr-FR.txt
Md fr-FR
al /embed:Greetings.fr-FR.resources /culture:fr-FR /out:fr-FR\Example.resources.dll

resgen Greetings.ru-RU.txt
Md ru-RU
al /embed:Greetings.ru-RU.resources /culture:ru-RU /out:ru-RU\Example.resources.dll

Pobieranie zasobów

GetObject(String) Metody i GetString(String) umożliwiają uzyskanie dostępu do określonego zasobu. Możesz również wywołać metodę GetStream(String) , aby pobrać zasoby inne niż ciągi jako tablicę bajtów. Domyślnie w aplikacji, która ma zlokalizowane zasoby, te metody zwracają zasób kultury określonej przez bieżącą kulturę interfejsu użytkownika wątku, który wykonał wywołanie. Zobacz poprzednią sekcję ResourceManager i zasoby specyficzne dla kultury, aby uzyskać więcej informacji na temat sposobu definiowania bieżącej kultury interfejsu użytkownika wątku. Jeśli menedżer zasobów nie może odnaleźć zasobu dla kultury interfejsu użytkownika bieżącego wątku, używa procesu rezerwowego w celu pobrania określonego zasobu. Jeśli menedżer zasobów nie może odnaleźć żadnych zlokalizowanych zasobów, używa zasobów domyślnej kultury. Aby uzyskać więcej informacji na temat reguł rezerwowych zasobów, zobacz sekcję "Proces rezerwowania zasobów" artykułu Tworzenie pakietów i wdrażanie zasobów.

Uwaga

Jeśli nie można odnaleźć pliku resources określonego w konstruktorze ResourceManager klasy, próba pobrania zasobu zgłasza MissingManifestResourceException wyjątek lub MissingSatelliteAssemblyException . Aby uzyskać informacje na temat obsługi wyjątku, zobacz sekcję Handle MissingManifestResourceException and MissingSatelliteAssemblyException Exceptions (Wyjątki wyjątków Handle MissingManifestResourceException i MissingSatelliteAssemblyException) w dalszej części tego artykułu.

W poniższym przykładzie użyto GetString metody w celu pobrania zasobów specyficznych dla kultury. Składa się z zasobów skompilowanych z plików .txt dla kultur angielskich (en), francuski (Francja) (fr-FR) i rosyjski (Rosja) (ru-RU). Przykład zmienia bieżącą kulturę i bieżącą kulturę interfejsu użytkownika na angielski (Stany Zjednoczone), francuski (Francja), rosyjski (Rosja) i szwedzki (Szwecja). Następnie wywołuje metodę GetString , aby pobrać zlokalizowany ciąg, który jest wyświetlany wraz z bieżącym dniem i miesiącem. Zwróć uwagę, że dane wyjściowe wyświetlają odpowiedni zlokalizowany ciąg z wyjątkiem sytuacji, gdy bieżąca kultura interfejsu użytkownika to Szwedzki (Szwecja). Ponieważ szwedzkie zasoby językowe są niedostępne, aplikacja używa zasobów kultury domyślnej, czyli języka angielskiego.

Przykład wymaga plików zasobów opartych na tekście wymienionych w poniższej tabeli. Każdy z nich ma jeden zasób ciągu o nazwie DateStart.

Kultura Nazwa pliku Nazwa zasobu Wartość zasobu
en-US DateStrings.txt DateStart Dzisiaj jest
fr-FR DateStrings.fr-FR.txt DateStart Aujourd'hui, c'est le
ru-RU DateStrings.ru-RU.txt DateStart Сегодня

Oto kod źródłowy dla przykładu (ShowDate.vb dla wersji Visual Basic lub ShowDate.cs dla wersji języka C# kodu).

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

[assembly: NeutralResourcesLanguage("en")]

public class ShowDateEx
{
    public static void Main()
    {
        string[] cultureNames = { "en-US", "fr-FR", "ru-RU", "sv-SE" };
        ResourceManager rm = new ResourceManager("DateStrings",
                                                 typeof(Example).Assembly);

        foreach (var cultureName in cultureNames)
        {
            CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
            Thread.CurrentThread.CurrentCulture = culture;
            Thread.CurrentThread.CurrentUICulture = culture;

            Console.WriteLine("Current UI Culture: {0}",
                              CultureInfo.CurrentUICulture.Name);
            string dateString = rm.GetString("DateStart");
            Console.WriteLine("{0} {1:M}.\n", dateString, DateTime.Now);
        }
    }
}
// The example displays output similar to the following:
//       Current UI Culture: en-US
//       Today is February 03.
//       
//       Current UI Culture: fr-FR
//       Aujourd'hui, c'est le 3 février
//       
//       Current UI Culture: ru-RU
//       Сегодня февраля 03.
//       
//       Current UI Culture: sv-SE
//       Today is den 3 februari.
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly:NeutralResourcesLanguage("en")>

Module Example5
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "fr-FR", "ru-RU", "sv-SE"}
        Dim rm As New ResourceManager("DateStrings",
                                    GetType(Example5).Assembly)

        For Each cultureName In cultureNames
            Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureName)
            Thread.CurrentThread.CurrentCulture = culture
            Thread.CurrentThread.CurrentUICulture = culture

            Console.WriteLine("Current UI Culture: {0}",
                           CultureInfo.CurrentUICulture.Name)
            Dim dateString As String = rm.GetString("DateStart")
            Console.WriteLine("{0} {1:M}.", dateString, Date.Now)
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays output similar to the following:
'       Current UI Culture: en-US
'       Today is February 03.
'       
'       Current UI Culture: fr-FR
'       Aujourd'hui, c'est le 3 février
'       
'       Current UI Culture: ru-RU
'       Сегодня февраля 03.
'       
'       Current UI Culture: sv-SE
'       Today is den 3 februari.

Aby skompilować ten przykład, utwórz plik wsadowy zawierający następujące polecenia i uruchom go w wierszu polecenia. Jeśli używasz języka C#, określ csc zamiast vbc i showdate.cs zamiast showdate.vb.

resgen DateStrings.txt
vbc showdate.vb /resource:DateStrings.resources

md fr-FR
resgen DateStrings.fr-FR.txt
al /out:fr-FR\Showdate.resources.dll /culture:fr-FR /embed:DateStrings.fr-FR.resources

md ru-RU
resgen DateStrings.ru-RU.txt
al /out:ru-RU\Showdate.resources.dll /culture:ru-RU /embed:DateStrings.ru-RU.resources

Istnieją dwa sposoby pobierania zasobów określonej kultury innej niż bieżąca kultura interfejsu użytkownika:

  • Możesz wywołać metodę GetString(String, CultureInfo), lub GetStream(String, CultureInfo) , GetObject(String, CultureInfo)aby pobrać zasób dla określonej kultury. Jeśli nie można odnaleźć zlokalizowanego zasobu, menedżer zasobów używa procesu rezerwowego zasobu do zlokalizowania odpowiedniego zasobu.
  • Metodę GetResourceSet można wywołać, aby uzyskać ResourceSet obiekt reprezentujący zasoby dla określonej kultury. W wywołaniu metody można określić, czy sondy menedżera zasobów dla kultur nadrzędnych, jeśli nie mogą znaleźć zlokalizowanych zasobów, lub czy po prostu wracają do zasobów kultury domyślnej. Następnie możesz użyć ResourceSet metod, aby uzyskać dostęp do zasobów (zlokalizowanych dla tej kultury) według nazwy lub wyliczyć zasoby w zestawie.

Obsługa wyjątków MissingManifestResourceException i MissingSatelliteAssemblyException

Jeśli spróbujesz pobrać określony zasób, ale menedżer zasobów nie może znaleźć tego zasobu i nie zdefiniowano żadnej domyślnej kultury lub nie można odnaleźć zasobów kultury domyślnej, menedżer zasobów zgłasza MissingManifestResourceException wyjątek, jeśli oczekuje się znalezienia zasobów w zestawie głównym lub jeśli MissingSatelliteAssemblyException spodziewa się znaleźć zasoby w zestawie satelitarnym. Należy pamiętać, że wyjątek jest zgłaszany podczas wywoływania metody pobierania zasobów, takiej jak GetString lub GetObject, a nie podczas tworzenia wystąpienia ResourceManager obiektu.

Wyjątek jest zwykle zgłaszany w następujących warunkach:

  • Odpowiedni plik zasobu lub zestaw satelitarny nie istnieje. Jeśli menedżer zasobów oczekuje, że domyślne zasoby aplikacji zostaną osadzone w głównym zestawie aplikacji, są one nieobecne. NeutralResourcesLanguageAttribute Jeśli atrybut wskazuje, że domyślne zasoby aplikacji znajdują się w zestawie satelitarnym, nie można odnaleźć tego zestawu. Podczas kompilowania aplikacji upewnij się, że zasoby są osadzone w zestawie głównym lub że wymagany zestaw satelitarny jest generowany i jest odpowiednio nazwany. Jego nazwa powinna mieć postać appName.resources.dll i powinna znajdować się w katalogu o nazwie po kulturze, której zasoby zawiera.

  • Aplikacja nie ma zdefiniowanej domyślnej ani neutralnej kultury. NeutralResourcesLanguageAttribute Dodaj atrybut do pliku kodu źródłowego lub do pliku informacji o projekcie (AssemblyInfo.vb dla aplikacji Visual Basic lub AssemblyInfo.cs dla aplikacji języka C#).

  • Parametr baseName w konstruktorze ResourceManager(String, Assembly) nie określa nazwy pliku resources. Nazwa powinna zawierać w pełni kwalifikowaną przestrzeń nazw pliku zasobu, ale nie jej rozszerzenie nazwy pliku. Zazwyczaj pliki zasobów utworzone w programie Visual Studio zawierają nazwy przestrzeni nazw, ale pliki zasobów utworzone i skompilowane w wierszu polecenia nie. Nazwy osadzonych plików resources można określić, kompilując i uruchamiając następujące narzędzie. Jest to aplikacja konsolowa, która akceptuje nazwę głównego zestawu lub zestawu satelitarnego jako parametr wiersza polecenia. Wyświetla on ciągi, które powinny być podane jako baseName parametr, aby menedżer zasobów mógł poprawnie zidentyfikować zasób.

    using System;
    using System.IO;
    using System.Reflection;
    
    public class Example0
    {
       public static void Main()
       {
          if (Environment.GetCommandLineArgs().Length == 1) { 
             Console.WriteLine("No filename.");
             return;
          }
          
          string filename = Environment.GetCommandLineArgs()[1].Trim();
          // Check whether the file exists.
          if (! File.Exists(filename)) {
             Console.WriteLine("{0} does not exist.", filename);
             return;
          }   
          
          // Try to load the assembly.
          Assembly assem = Assembly.LoadFrom(filename);
          Console.WriteLine("File: {0}", filename);
             
          // Enumerate the resource files.
          string[] resNames = assem.GetManifestResourceNames();
          if (resNames.Length == 0)
             Console.WriteLine("   No resources found.");
    
          foreach (var resName in resNames)
             Console.WriteLine("   Resource: {0}", resName.Replace(".resources", ""));
    
          Console.WriteLine();
       }
    }
    
    Imports System.IO
    Imports System.Reflection
    Imports System.Resources
    
    Module Example
       Public Sub Main()
          If Environment.GetCommandLineArgs.Length = 1 Then 
             Console.WriteLine("No filename.")
             Exit Sub
          End If
          Dim filename As String = Environment.GetCommandLineArgs(1).Trim()
          ' Check whether the file exists.
          If Not File.Exists(filename) Then
             Console.WriteLine("{0} does not exist.", filename)
             Exit Sub
          End If   
          
          ' Try to load the assembly.
          Dim assem As Assembly = Assembly.LoadFrom(filename)
          Console.WriteLine("File: {0}", filename)
             
          ' Enumerate the resource files.
          Dim resNames() As String = assem.GetManifestResourceNames()
          If resNames.Length = 0 Then
             Console.WriteLine("   No resources found.")
          End If
          For Each resName In resNames
             Console.WriteLine("   Resource: {0}", resName.Replace(".resources", ""))
          Next
          Console.WriteLine()
       End Sub
    End Module
    

Jeśli jawnie zmieniasz bieżącą kulturę aplikacji, pamiętaj również, że menedżer zasobów pobiera zestaw zasobów na podstawie wartości CultureInfo.CurrentUICulture właściwości, a nie CultureInfo.CurrentCulture właściwości. Zazwyczaj w przypadku zmiany jednej wartości należy również zmienić drugą.

Przechowywanie wersji zasobów

Ponieważ główny zestaw zawierający domyślne zasoby aplikacji jest oddzielony od zestawów satelitarnych aplikacji, można zwolnić nową wersję głównego zestawu bez ponownego wdrażania zestawów satelickich. Atrybut służy do używania SatelliteContractVersionAttribute istniejących zestawów satelickich i instruuje menedżera zasobów, aby nie wdrażał ich ponownie przy użyciu nowej wersji głównego zestawu,

Aby uzyskać więcej informacji na temat obsługi wersji zestawów satelickich, zobacz artykuł Pobieranie zasobów.

<węzeł pliku konfiguracji satelliteassemblies>

Uwaga

Ta sekcja jest specyficzna dla aplikacji .NET Framework.

W przypadku plików wykonywalnych, które są wdrażane i uruchamiane z witryny internetowej (pliki HREF .exe), ResourceManager obiekt może sondować zestawy satelitarne w Internecie, co może zaszkodzić wydajności aplikacji. Aby wyeliminować problem z wydajnością, możesz ograniczyć tę sondę do zestawów satelitarnych wdrożonych w aplikacji. W tym celu należy utworzyć <satelliteassemblies> węzeł w pliku konfiguracji aplikacji, aby określić, że wdrożono określony zestaw kultur dla aplikacji, i że ResourceManager obiekt nie powinien próbować sondować pod kątem żadnej kultury, która nie znajduje się na liście w tym węźle.

Uwaga

Preferowaną alternatywą do utworzenia węzła <satelliteassemblies> jest użycie funkcji manifestu wdrażania Technologii ClickOnce.

W pliku konfiguracji aplikacji utwórz sekcję podobną do następującej:

<?xml version ="1.0"?>
<configuration>
  <satelliteassemblies>
    <assembly name="MainAssemblyName, Version=versionNumber, Culture=neutral, PublicKeyToken=null|yourPublicKeyToken">
      <culture>cultureName1</culture>
      <culture>cultureName2</culture>
      <culture>cultureName3</culture>
    </assembly>
  </satelliteassemblies>
</configuration>

Edytuj te informacje o konfiguracji w następujący sposób:

  • Określ co najmniej jeden <assembly> węzeł dla każdego wdrażanego głównego zestawu, w którym każdy węzeł określa w pełni kwalifikowaną nazwę zestawu. Określ nazwę głównego zestawu zamiast MainAssemblyName i określ Versionwartości atrybutów , PublicKeyTokeni Culture , które odpowiadają głównemu zestawowi.

    W przypadku atrybutu Version określ numer wersji zestawu. Na przykład pierwsza wersja zestawu może być numerem wersji 1.0.0.0.

    W przypadku atrybutu PublicKeyToken określ słowo kluczowe null , jeśli zestaw nie został podpisany przy użyciu silnej nazwy lub określ token klucza publicznego, jeśli zestaw został podpisany.

    Dla atrybutu Culture określ słowo kluczowe neutral , aby wyznaczyć główny zestaw i spowodować ResourceManager , że klasa będzie sondować tylko dla kultur wymienionych w <culture> węzłach.

    Aby uzyskać więcej informacji na temat w pełni kwalifikowanych nazw zestawów, zobacz artykuł Nazwy zestawów. Aby uzyskać więcej informacji na temat zestawów o silnych nazwach, zobacz artykuł Tworzenie i używanie zestawów o silnych nazwach.

  • Określ co najmniej jeden <culture> węzeł o określonej nazwie kultury, na przykład "fr-FR" lub neutralną nazwę kultury, taką jak "fr".

Jeśli zasoby są potrzebne dla żadnego zestawu, który nie znajduje się na liście w węźle <satelliteassemblies> , ResourceManager sondy klas dla kultur przy użyciu standardowych reguł sondowania.

Aplikacje systemu Windows 8.x

Ważne

Mimo że klasa jest obsługiwana ResourceManager w aplikacjach systemu Windows 8.x, nie zalecamy jej użycia. Tej klasy należy używać tylko podczas tworzenia projektów biblioteki klas przenośnych, które mogą być używane z aplikacjami systemu Windows 8.x. Aby pobrać zasoby z aplikacji systemu Windows 8.x, zamiast tego użyj klasy Windows.ApplicationModel.Resources.ResourceLoader .

W przypadku aplikacji ResourceManager systemu Windows 8.x klasa pobiera zasoby z plików indeksu zasobów pakietu (PRI). Pojedynczy plik PRI (plik PRI pakietu aplikacji) zawiera zasoby zarówno dla kultury domyślnej, jak i wszystkich zlokalizowanych kultur. Za pomocą narzędzia MakePRI można utworzyć plik PRI na podstawie jednego lub większej liczby plików zasobów, które są w formacie zasobu XML (resw). W przypadku zasobów uwzględnionych w projekcie programu Visual Studio program Visual Studio automatycznie obsługuje proces tworzenia i pakowania pliku PRI. Następnie możesz użyć klasy .NET ResourceManager , aby uzyskać dostęp do zasobów aplikacji lub biblioteki.

Możesz utworzyć wystąpienie ResourceManager obiektu dla aplikacji systemu Windows 8.x w taki sam sposób, jak w przypadku aplikacji klasycznej.

Następnie możesz uzyskać dostęp do zasobów dla określonej kultury, przekazując nazwę zasobu do pobrania do GetString(String) metody . Domyślnie ta metoda zwraca zasób dla kultury określonej przez bieżącą kulturę interfejsu użytkownika wątku, który wykonał wywołanie. Zasoby dla określonej kultury można również pobrać, przekazując nazwę zasobu i CultureInfo obiekt reprezentujący kulturę, której zasób ma zostać pobrany do GetString(String, CultureInfo) metody. Jeśli nie można odnaleźć zasobu dla bieżącej kultury interfejsu użytkownika lub określonej kultury, menedżer zasobów używa listy rezerwowej języka interfejsu użytkownika w celu zlokalizowania odpowiedniego zasobu.

Przykłady

W poniższym przykładzie pokazano, jak używać kultury jawnej i niejawnej bieżącej kultury interfejsu użytkownika w celu uzyskania zasobów ciągów z głównego zestawu i zestawu satelitarnego. Aby uzyskać więcej informacji, zobacz sekcję "Lokalizacje katalogów dla zestawów satelitarnych nie zainstalowano w globalnej pamięci podręcznej zestawów" w temacie Tworzenie zestawów satelickich.

Aby uruchomić ten przykład:

  1. W katalogu aplikacji utwórz plik o nazwie rmc.txt zawierający następujące ciągi zasobów:

    day=Friday
    year=2006
    holiday="Cinco de Mayo"
    
  2. Użyj generatora plików zasobów, aby wygenerować plik zasobów rmc.resources z pliku wejściowego rmc.txt w następujący sposób:

    resgen rmc.txt
    
  3. Utwórz podkatalog katalogu aplikacji i nadaj mu nazwę "es-MX". Jest to nazwa kultury zestawu satelitarnego, który zostanie utworzony w następnych trzech krokach.

  4. Utwórz plik o nazwie rmc.es-MX.txt w katalogu es-MX zawierającym następujące ciągi zasobów:

    day=Viernes
    year=2006
    holiday="Cinco de Mayo"
    
  5. Użyj generatora plików zasobów, aby wygenerować plik zasobów rmc.es-MX.resources z pliku wejściowego rmc.es-MX.txt w następujący sposób:

    resgen rmc.es-MX.txt
    
  6. Załóżmy, że nazwa pliku dla tego przykładu to rmc.vb lub rmc.cs. Skopiuj następujący kod źródłowy do pliku. Następnie skompiluj go i osadź główny plik zasobu zestawu rmc.resources w zestawie wykonywalny. Jeśli używasz kompilatora języka Visual Basic, składnia to:

    vbc rmc.vb /resource:rmc.resources
    

    Odpowiadająca składnia kompilatora języka C# to:

    csc /resource:rmc.resources rmc.cs
    
  7. Użyj konsolidatora zestawów, aby utworzyć zestaw satelitarny. Jeśli podstawowa nazwa aplikacji to rmc, nazwa zestawu satelitarnego musi być rmc.resources.dll. Zestaw satelitarny należy utworzyć w katalogu es-MX. Jeśli es-MX jest bieżącym katalogm, użyj następującego polecenia:

    al /embed:rmc.es-MX.resources /c:es-MX /out:rmc.resources.dll
    
  8. Uruchom rmc.exe, aby uzyskać i wyświetlić osadzone ciągi zasobów.

    using System;
    using System.Globalization;
    using System.Resources;
    
    class Example2
    {
        public static void Main()
        {
            string day;
            string year;
            string holiday;
            string celebrate = "{0} will occur on {1} in {2}.\n";
    
            // Create a resource manager.
            ResourceManager rm = new ResourceManager("rmc",
                                     typeof(Example).Assembly);
    
            Console.WriteLine("Obtain resources using the current UI culture.");
    
            // Get the resource strings for the day, year, and holiday
            // using the current UI culture.
            day = rm.GetString("day");
            year = rm.GetString("year");
            holiday = rm.GetString("holiday");
            Console.WriteLine(celebrate, holiday, day, year);
    
            // Obtain the es-MX culture.
            CultureInfo ci = new CultureInfo("es-MX");
    
            Console.WriteLine("Obtain resources using the es-MX culture.");
    
            // Get the resource strings for the day, year, and holiday
            // using the specified culture.
            day = rm.GetString("day", ci);
            year = rm.GetString("year", ci);
            holiday = rm.GetString("holiday", ci);
            // ---------------------------------------------------------------
            // Alternatively, comment the preceding 3 code statements and
            // uncomment the following 4 code statements:
            // ----------------------------------------------------------------
            // Set the current UI culture to "es-MX" (Spanish-Mexico).
            //    Thread.CurrentThread.CurrentUICulture = ci;
    
            // Get the resource strings for the day, year, and holiday
            // using the current UI culture. Use those strings to
            // display a message.
            //    day  = rm.GetString("day");
            //    year = rm.GetString("year");
            //    holiday = rm.GetString("holiday");
            // ---------------------------------------------------------------
    
            // Regardless of the alternative that you choose, display a message
            // using the retrieved resource strings.
            Console.WriteLine(celebrate, holiday, day, year);
        }
    }
    /*
    This example displays the following output:
    
       Obtain resources using the current UI culture.
       "5th of May" will occur on Friday in 2006.
    
       Obtain resources using the es-MX culture.
       "Cinco de Mayo" will occur on Viernes in 2006.
    */
    
    Imports System.Resources
    Imports System.Reflection
    Imports System.Threading
    Imports System.Globalization
    
    Class Example4
        Public Shared Sub Main()
            Dim day As String
            Dim year As String
            Dim holiday As String
            Dim celebrate As String = "{0} will occur on {1} in {2}." & vbCrLf
    
            ' Create a resource manager. 
            Dim rm As New ResourceManager("rmc", GetType(Example4).Assembly)
    
            Console.WriteLine("Obtain resources using the current UI culture.")
    
            ' Get the resource strings for the day, year, and holiday 
            ' using the current UI culture. 
            day = rm.GetString("day")
            year = rm.GetString("year")
            holiday = rm.GetString("holiday")
            Console.WriteLine(celebrate, holiday, day, year)
    
            ' Obtain the es-MX culture.
            Dim ci As New CultureInfo("es-MX")
    
            Console.WriteLine("Obtain resources using the es-MX culture.")
    
            ' Get the resource strings for the day, year, and holiday 
            ' using the es-MX culture.  
            day = rm.GetString("day", ci)
            year = rm.GetString("year", ci)
            holiday = rm.GetString("holiday", ci)
    
            ' ---------------------------------------------------------------
            ' Alternatively, comment the preceding 3 code statements and 
            ' uncomment the following 4 code statements:
            ' ----------------------------------------------------------------
            ' Set the current UI culture to "es-MX" (Spanish-Mexico).
            '    Thread.CurrentThread.CurrentUICulture = ci
            ' Get the resource strings for the day, year, and holiday 
            ' using the current UI culture. 
            '    day  = rm.GetString("day")
            '    year = rm.GetString("year")
            '    holiday = rm.GetString("holiday")
            ' ---------------------------------------------------------------
    
            ' Regardless of the alternative that you choose, display a message 
            ' using the retrieved resource strings.
            Console.WriteLine(celebrate, holiday, day, year)
        End Sub
    End Class
    ' This example displays the following output:
    'Obtain resources using the current UI culture.
    '"5th of May" will occur on Friday in 2006.
    '
    'Obtain resources using the es-MX culture.
    '"Cinco de Mayo" will occur on Viernes in 2006.