System.Resources.ResourceManager 类

本文提供了此 API 参考文档的补充说明。

重要

使用不受信任的数据调用此类中的方法存在安全风险。 仅使用受信任的数据调用此类中的方法。 有关详细信息,请参阅 “验证所有输入”。

ResourceManager 类从嵌入程序集中的二进制 .resources 文件或独立 .resources 文件中检索资源。 如果应用已在附属程序集部署本地化和本地化资源,则会查找区域性特定的资源,在本地化资源不存在时提供资源回退,并支持资源序列化。

桌面应用

对于桌面应用,类 ResourceManager 从二进制资源(.resources)文件检索资源。 通常,语言编译器或 程序集链接器(AL.exe) 将这些资源文件嵌入程序集中。 还可以通过调用CreateFileBasedResourceManager该方法,使用ResourceManager对象直接从未嵌入程序集的 .resources 文件中检索资源。

注意

在 ASP.NET 应用中使用独立 .resources 文件会中断 XCOPY 部署,因为资源将一直被锁定,直到方法显式释放 ReleaseAllResources 它们。 如果要使用 ASP.NET 应用部署资源,则应将 .resources 文件编译为附属程序集。

在基于资源的应用中,一个 .resources 文件包含默认区域性的资源,如果找不到特定于区域性的资源,则使用其资源。 例如,如果应用的默认区域性为英语(en),则每当找不到特定区域性的本地化资源(例如英语(美国)或法语(法国)(fr-FR)时,都会使用英语语言资源。 通常,默认区域性的资源嵌入在主应用程序集中,其他本地化区域性的资源嵌入附属程序集中。 附属程序集仅包含资源。 它们的根文件名与主程序集相同,扩展名为 .resources.dll。 对于未在全局程序集缓存中注册程序集的应用,附属程序集存储在名称对应于程序集区域性的应用子目录中。

创建资源

开发基于资源的应用时,会将资源信息存储在文本文件(具有.txt或 .restext 扩展名的文件)或 XML 文件(扩展名为 .resx 的文件) 中。 然后使用资源文件生成器(Resgen.exe)编译文本或 XML 文件,以创建二进制 .resources 文件。 然后,可以使用编译器选项(例如 /resources C# 和 Visual Basic 编译器)将生成的 .resources 文件嵌入到可执行文件或库中,也可以使用程序集链接器(AI.exe)将其嵌入附属程序集中。 如果在 Visual Studio 项目中包括 .resx 文件,Visual Studio 会在生成过程中自动处理默认和本地化资源的编译和嵌入。

理想情况下,应为应用支持的每种语言创建资源,或者至少为每个语言的有意义的子集创建资源。 二进制 .resources 文件名遵循命名约定基名称cultureName.resources,其中 basename 是应用的名称或类的名称,具体取决于所需的详细信息级别。 该 CultureInfo.Name 属性用于确定 cultureName。 应用默认区域性的资源应命名为 basename.resources

例如,假设程序集在一个资源文件中有多个资源,该资源文件中具有基本名称 MyResources。 这些资源文件的名称应包括适用于日本(日语)区域性的 MyResources.ja-JP.resources、德国文化的 MyResources.de.resources、简化的中国文化的 MyResources.zh-CHS.resources,以及法语(比利时)区域性的 MyResources.fr-BE.resources。 默认资源文件应命名为 MyResources.resources。 特定于区域性的资源文件通常打包在每个区域性的附属程序集中。 默认资源文件应嵌入应用的主程序集中。

请注意, 程序集链接器 允许将资源标记为私有,但应始终将它们标记为公共,以便其他程序集可以访问它们。 (由于附属程序集不包含任何代码,因此标记为私有的资源无法通过任何机制对应用使用。

有关创建、打包和部署资源的详细信息,请参阅文章 :创建资源文件创建附属程序集以及 打包和部署资源

实例化 ResourceManager 对象

通过调用其中一个 ResourceManager 类构造函数重载来实例化从嵌入式 .resources 文件中检索资源的对象。 这与特定 .resources 文件以及附属程序集中任何关联的本地化 .resources 文件紧密耦 ResourceManager 合对象。

最常见的两个构造函数是:

  • ResourceManager(String, Assembly) 根据提供的两条信息查找资源:.resources 文件的基名称,以及默认 .resources 文件所在的程序集。 基名称包括 .resources 文件的命名空间和根名称,而不包含其区域性或扩展名。 请注意,从命令行编译的 .resources 文件通常不包括命名空间名称,而 Visual Studio 环境中创建的 .resources 文件通常包括命名空间名称。 例如,如果资源文件名为 MyCompany.StringResources.resources,并且 ResourceManager 构造函数是从名为静态 Example.Main方法调用的,则以下代码实例化可从 ResourceManager .resources 文件检索资源的对象:

    ResourceManager rm = new ResourceManager("MyCompany.StringResources",
                                             typeof(Example).Assembly);
    
    Dim rm As New ResourceManager("MyCompany.StringResources",
                                GetType(Example2).Assembly)
    
  • ResourceManager(Type) 根据类型对象中的信息查找附属程序集中的资源。 该类型的完全限定名称对应于 .resources 文件的基名称,没有文件扩展名。 在使用 Visual Studio 资源设计器创建的桌面应用中,Visual Studio 将创建一个包装类,该包装器类的完全限定名称与 .resources 文件的根名称相同。 例如,如果资源文件名为 MyCompany.StringResources.resources,并且有一 MyCompany.StringResources个名为包装类,则以下代码实例化一个 ResourceManager 对象,该对象可以从 .resources 文件检索资源:

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

如果找不到适当的资源,构造函数调用将创建一个有效的 ResourceManager 对象。 但是,尝试检索资源会 MissingManifestResourceException 引发异常。 有关处理异常的信息,请参阅 本文后面的 Handle MissingManifestResourceException 和 MissingSatelliteAssemblyException Exceptions 部分。

以下示例演示如何实例化 ResourceManager 对象。 它包含名为 ShowTime.exe 的可执行文件的源代码。 它还包括包含以下名为Strings.txt的文本文件,其中包含单个字符串资源: TimeHeader

TimeHeader=The current time is

可以使用批处理文件生成资源文件并将其嵌入可执行文件。 下面是使用 C# 编译器生成可执行文件的批处理文件:

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

对于 Visual Basic 编译器,可以使用以下批处理文件:

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 和区域性特定的资源

本地化应用需要部署资源,如打包和部署资源一文中所述。 如果正确配置了程序集,资源管理器会根据当前线程 Thread.CurrentUICulture 的属性确定要检索的资源。 (该属性还返回当前线程的 UI 区域性。例如,如果使用主程序集中的默认英语语言资源以及两个附属程序集中的法语和俄语语言资源编译应用,并且该 Thread.CurrentUICulture 属性设置为 fr-FR,则资源管理器将检索法语资源。

可以显式或隐式设置 CurrentUICulture 属性。 设置它的方式决定了对象如何 ResourceManager 根据区域性检索资源:

  • 如果将属性显式设置为 Thread.CurrentUICulture 特定区域性,则无论用户的浏览器或操作系统语言如何,资源管理器始终检索该区域性的资源。 请考虑使用默认英语语言资源和包含英语(美国)、法语(法国)和俄语(俄罗斯)的资源的三个附属程序集编译的应用。 CurrentUICulture如果该属性设置为 fr-FR,则ResourceManager对象始终检索法语(法国)资源,即使用户的操作系统语言不是法语。 在显式设置属性之前,请确保这是所需的行为。

    在 ASP.NET 应用中,必须显式设置 Thread.CurrentUICulture 属性,因为服务器上的设置不太可能与传入的客户端请求匹配。 ASP.NET 应用可以将属性显式设置为 Thread.CurrentUICulture 用户的浏览器接受语言。

    显式设置该 Thread.CurrentUICulture 属性定义该线程的当前 UI 区域性。 它不会影响应用中任何其他线程的当前 UI 区域性。

  • 可以通过将表示该区域性的对象分配给 CultureInfo 静态 CultureInfo.DefaultThreadCurrentUICulture 属性来设置应用域中所有线程的 UI 区域性。

  • 如果未显式设置当前 UI 区域性,并且未为当前应用域定义默认区域性,则 CultureInfo.CurrentUICulture 属性由 Windows GetUserDefaultUILanguage 函数隐式设置。 此函数由 多语言用户界面 (MUI)提供,使用户能够设置默认语言。 如果用户未设置 UI 语言,则默认为系统安装的语言,即操作系统资源的语言。

以下简单的“Hello world”示例显式设置当前 UI 区域性。 它包含三种文化的资源:英语(美国)或 en-US、法语(法国)或 fr-FR、俄语(俄罗斯)或 ru-RU。 en-US 资源包含在名为Greetings.txt的文本文件中:

HelloString=Hello world!

fr-FR 资源包含在名为Greetings.fr-FR.txt的文本文件中:

HelloString=Salut tout le monde!

ru-RU 资源包含在名为Greetings.ru-RU.txt的文本文件中:

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

下面是示例的源代码(Visual Basic 版本Example.vb或 C# 版本的Example.cs):

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.
'       Всем привет!

若要编译此示例,请创建一个包含以下命令的批处理(.bat)文件,并从命令提示符运行它。 如果使用的是 C#,请指定csc而不是vbc指定Example.vb而不是 Example.cs

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

检索资源

调用 GetObject(String)GetString(String) 方法来访问特定资源。 还可以调用 GetStream(String) 该方法以字节数组的形式检索非字符串资源。 默认情况下,在具有本地化资源的应用中,这些方法返回由发出调用的线程的当前 UI 区域性确定的区域性的资源。 有关如何定义线程的当前 UI 区域性的详细信息,请参阅上一部分 ResourceManager 和特定于区域性的资源。 如果资源管理器找不到当前线程 UI 区域性的资源,则它使用回退进程来检索指定的资源。 如果资源管理器找不到任何本地化的资源,它将使用默认区域性的资源。 有关资源回退规则的详细信息,请参阅打包和部署资源一文中的“资源回退过程”部分。

注意

如果找不到类构造函数中指定的 ResourceManager .resources 文件,则尝试检索资源将引发或MissingManifestResourceExceptionMissingSatelliteAssemblyException异常。 有关处理异常的信息,请参阅 本文后面的 Handle MissingManifestResourceException 和 MissingSatelliteAssemblyException Exceptions 部分。

以下示例使用 GetString 该方法检索区域性特定的资源。 它包括从英语(en)、法语(法国)和俄罗斯(俄罗斯)(ru-RU)文化的.txt文件中编译的资源。 本示例将当前文化和当前 UI 文化更改为英语(美国)、法语(法国)、俄语(俄罗斯)和瑞典语(瑞典)。 然后,它会调用 GetString 该方法来检索本地化字符串,该字符串与当前日期和月份一起显示。 请注意,输出显示适当的本地化字符串,除非当前 UI 区域性为瑞典(瑞典)。 由于瑞典语言资源不可用,因此应用会改用默认区域性的资源,即英语。

此示例需要下表中列出的基于文本的资源文件。 每个资源都有一个名为 DateStart 的字符串资源。

区域性 文件名 资源名称 资源值
en-US DateStrings.txt DateStart 今天是
fr-FR DateStrings.fr-FR.txt DateStart Aujourd'hui, c'est le
ru-RU DateStrings.ru-RU.txt DateStart Сегодня

下面是示例的源代码(visual Basic 版本ShowDate.vb或 C# 版本的代码ShowDate.cs)。

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.

若要编译此示例,请创建一个包含以下命令的批处理文件,并从命令提示符运行它。 如果使用的是 C#,请指定csc而不是vbc指定showdate.vb而不是 showdate.cs

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

有两种方法可以检索当前 UI 区域性以外的特定区域性的资源:

  • 可以调用GetString(String, CultureInfo)GetObject(String, CultureInfo)GetStream(String, CultureInfo)或方法来检索特定区域性的资源。 如果找不到本地化资源,资源管理器将使用资源回退过程来查找适当的资源。
  • 可以调用 GetResourceSet 该方法来获取表示 ResourceSet 特定区域性的资源的对象。 在方法调用中,可以确定如果找不到本地化资源,资源管理器是否探测父区域性,还是只回退到默认区域性的资源。 然后 ResourceSet ,可以使用这些方法按名称访问资源(本地化为区域性),或枚举集中的资源。

处理 MissingManifestResourceException 和 MissingSatelliteAssemblyException 异常

如果尝试检索特定资源,但资源管理器找不到该资源,并且未定义默认区域性,或者无法找到默认区域性的资源,则如果资源管理器希望查找主程序集中的资源,或者MissingSatelliteAssemblyException如果资源需要查找附属程序集中的资源,则资源管理器将引发MissingManifestResourceException异常。 请注意,调用资源检索方法(例如 GetStringGetObject)而不是实例化 ResourceManager 对象时,将引发异常。

异常通常在以下情况下引发:

  • 不存在相应的资源文件或附属程序集。 如果资源管理器要求应用的默认资源嵌入到主应用程序集中,则不存在这些资源。 NeutralResourcesLanguageAttribute如果该属性指示应用的默认资源驻留在附属程序集中,则找不到该程序集。 编译应用时,请确保资源嵌入主程序集或生成必要的附属程序集,并相应地命名。 其名称应采用 appName.resources.dll 格式,并且它应位于以区域性命名的目录中,其中包含其资源。

  • 应用未定义默认或非特定区域性。 将 NeutralResourcesLanguageAttribute 属性添加到源代码文件或项目信息文件(AssemblyInfo.vb Visual Basic 应用或 C# 应用AssemblyInfo.cs) 文件。

  • baseName构造函数中的ResourceManager(String, Assembly)参数未指定 .resources 文件的名称。 该名称应包括资源文件的完全限定命名空间,但不包括其文件扩展名。 通常,在 Visual Studio 中创建的资源文件包括命名空间名称,但在命令提示符下创建和编译的资源文件不会。 可以通过编译并运行以下实用工具来确定嵌入的 .resources 文件的名称。 这是一个控制台应用,它接受主程序集或附属程序集的名称作为命令行参数。 它显示应作为 baseName 参数提供的字符串,以便资源管理器能够正确标识资源。

    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
    

如果要显式更改应用程序的当前区域性,还应该记住,资源管理器会根据属性CultureInfo.CurrentCulture的值CultureInfo.CurrentUICulture而不是属性检索资源集。 通常,如果更改一个值,则还应更改另一个值。

资源版本控制

由于包含应用的默认资源的主程序集独立于应用的附属程序集,因此无需重新部署附属程序集即可释放主程序集的新版本。 使用 SatelliteContractVersionAttribute 特性使用现有附属程序集,并指示资源管理器不要使用新版主程序集重新部署它们,

有关对附属程序集的版本控制支持的详细信息,请参阅文章 “检索资源”。

<satelliteassemblies> 配置文件节点

注意

本部分特定于 .NET Framework 应用。

对于从网站(HREF .exe文件)部署和运行的可执行文件,该 ResourceManager 对象可能会通过 Web 探测附属程序集,这可能会损害应用的性能。 若要消除性能问题,可以将此探测限制为已随应用一起部署的附属程序集。 为此,请在应用的配置文件中创建一个 <satelliteassemblies> 节点,以指定已为应用部署了一组特定的区域性,并且 ResourceManager 该对象不应尝试探测该节点中未列出的任何区域性。

注意

创建 <satelliteassemblies> 节点的首选替代方法是使用 ClickOnce 部署清单 功能。

在应用的配置文件中,创建类似于下面的部分:

<?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>

编辑此配置信息,如下所示:

  • 为部署的每个主程序集指定一个或多个 <assembly> 节点,其中每个节点指定完全限定的程序集名称。 指定主程序集的名称代替 MainAssemblyName,并指定 Version与主程序集对应的 、 PublicKeyTokenCulture 属性值。

    对于属性 Version ,请指定程序集的版本号。 例如,程序集的第一个版本可能是版本号 1.0.0.0。

    对于该PublicKeyToken属性,如果尚未使用强名称对程序集进行签名,请指定关键字 (keyword)null;如果已对程序集签名,请指定公钥令牌。

    Culture对于属性,请指定关键字 (keyword)neutral以指定主程序集,并导致ResourceManager类仅探测节点中列出的<culture>区域性。

    有关完全限定程序集名称的详细信息,请参阅“程序集名称”一文。 有关强名称程序集的详细信息,请参阅文章 “创建和使用强名称程序集”。

  • 指定具有特定区域性名称(如“fr-FR”)或中性区域性名称(如“fr”)的一个或多个 <culture> 节点。

如果节点下 <satelliteassemblies> 未列出的任何程序集需要资源,则 ResourceManager 类会使用标准探测规则探测区域性。

Windows 8.x 应用

重要

尽管 Windows 8.x 应用中支持该 ResourceManager 类,但我们不建议使用它。 仅当你开发可与 Windows 8.x 应用一起使用的可移植类库项目时,才使用此类。 若要从 Windows 8.x 应用检索资源,请改用 Windows.ApplicationModel.Resources.ResourceLoader 类。

对于 Windows 8.x 应用,该 ResourceManager 类从包资源索引 (PRI) 文件检索资源。 单个 PRI 文件(应用程序包 PRI 文件)包含默认区域性和任何本地化区域性的资源。 使用 MakePRI 实用工具从 XML 资源 (.resw) 格式的一个或多个资源文件创建 PRI 文件。 对于 Visual Studio 项目中包含的资源,Visual Studio 会自动处理创建和打包 PRI 文件的过程。 然后,可以使用 .NET ResourceManager 类访问应用或库的资源。

你可以以与桌面应用相同的方式实例化 ResourceManager Windows 8.x 应用的对象。

然后,可以通过将要检索 GetString(String) 的资源的名称传递给方法来访问特定区域性的资源。 默认情况下,此方法返回由发出调用的线程的当前 UI 区域性确定的区域性的资源。 还可以通过传递资源的名称和 CultureInfo 表示要检索 GetString(String, CultureInfo) 其资源的区域性的对象来检索特定区域性的资源。 如果找不到当前 UI 区域性或指定区域性的资源,则资源管理器使用 UI 语言回退列表来查找合适的资源。

示例

以下示例演示如何使用显式区域性和隐式当前 UI 区域性从主程序集和附属程序集获取字符串资源。 有关详细信息,请参阅“创建附属程序集”主题的“未安装在全局程序集缓存中的附属程序集的目录位置”部分

若要运行此示例,

  1. 在应用目录中,创建一个名为rmc.txt的文件,其中包含以下资源字符串:

    day=Friday
    year=2006
    holiday="Cinco de Mayo"
    
  2. 使用资源文件生成器从rmc.txt输入文件生成 rmc.resources 资源文件,如下所示:

    resgen rmc.txt
    
  3. 创建应用目录的子目录并将其命名为“es-MX”。 这是将在后续三个步骤中创建的附属程序集的区域性名称。

  4. 在包含以下资源字符串的 es-MX 目录中创建名为 rmc.es-MX.txt 的文件:

    day=Viernes
    year=2006
    holiday="Cinco de Mayo"
    
  5. 使用资源文件生成器从rmc.es-MX.txt输入文件生成 rmc.es-MX.resources 资源文件,如下所示:

    resgen rmc.es-MX.txt
    
  6. 假定此示例的文件名rmc.vb或rmc.cs。 将以下源代码复制到文件中。 然后编译它,并在可执行程序集中嵌入主程序集资源文件 rmc.resources。 如果使用 Visual Basic 编译器,则语法为:

    vbc rmc.vb /resource:rmc.resources
    

    C# 编译器的相应语法为:

    csc /resource:rmc.resources rmc.cs
    
  7. 使用程序集链接器创建附属程序集。 如果应用的基名称为 rmc,则必须rmc.resources.dll附属程序集名称。 应在 es-MX 目录中创建附属程序集。 如果 es-MX 是当前目录,请使用以下命令:

    al /embed:rmc.es-MX.resources /c:es-MX /out:rmc.resources.dll
    
  8. 运行rmc.exe以获取和显示嵌入的资源字符串。

    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.