System.Resources.ResourceManager.GetObject 方法

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

该方法 GetObject 用于检索非字符串资源。 这些值包括属于基元数据类型的值,例如 Int32Double图(如 System.Drawing.Bitmap 对象),或自定义序列化对象。 通常,返回的对象必须强制转换(在 C# 中)或转换为适当类型的对象(在 Visual Basic 中)。

IgnoreCase 属性确定与资源名称的比较 name 是区分大小写还是区分大小写(默认值)。

注意

这些方法可以引发的异常数可能多于列出的异常。 出现这种情况的一个原因是此方法调用的方法引发异常。 例如, FileLoadException 如果在部署或安装附属程序集时出错,或者 SerializationException 当用户定义类型反序列化时引发用户定义的异常,可能会引发异常。

GetObject(String) 方法

返回的资源已本地化为当前线程的 UI 区域性,该区域性由 CultureInfo.CurrentUICulture 该属性定义。 如果资源未针对该区域性进行本地化,资源管理器将使用回退规则来加载适当的资源。 如果未找到可用本地化资源集,则会 ResourceManager 回退默认区域性的资源。 如果未找到默认区域性的资源集,该方法将 MissingManifestResourceException 引发异常;如果预期资源集驻留在附属程序集中, MissingSatelliteAssemblyException 则引发异常。 如果资源管理器可以加载适当的资源集,但找不到名为 name的资源,该方法将 null返回。

示例

下面的示例使用 GetObject(String) 方法反序列化一个自定义对象。 该示例包括一个名为UIElements.cs的源代码文件(如果使用的是 Visual Basic),该文件定义了名为 PersonTable以下结构的UIElements.vb。 此结构应由显示表列的本地化名称的常规表显示例程使用。 请注意, PersonTable 结构标有 SerializableAttribute 属性。

using System;

[Serializable] public struct PersonTable
{
   public readonly int nColumns;
   public readonly string column1;
   public readonly string column2;
   public readonly string column3;
   public readonly int width1;
   public readonly int width2;
   public readonly int width3;

   public PersonTable(string column1, string column2, string column3,
                  int width1, int width2, int width3)
   {
      this.column1 = column1;
      this.column2 = column2;
      this.column3 = column3;
      this.width1 = width1;
      this.width2 = width2;
      this.width3 = width3;
      this.nColumns = typeof(PersonTable).GetFields().Length / 2;
   }
}
<Serializable> Public Structure PersonTable1
    Public ReadOnly nColumns As Integer
    Public ReadOnly column1 As String
    Public ReadOnly column2 As String
    Public ReadOnly column3 As String
    Public ReadOnly width1 As Integer
    Public ReadOnly width2 As Integer
    Public ReadOnly width3 As Integer

    Public Sub New(column1 As String, column2 As String, column3 As String,
                  width1 As Integer, width2 As Integer, width3 As Integer)
        Me.column1 = column1
        Me.column2 = column2
        Me.column3 = column3
        Me.width1 = width1
        Me.width2 = width2
        Me.width3 = width3
        Me.nColumns = Me.GetType().GetFields().Count \ 2
    End Sub
End Structure

名为 CreateResources.cs(或 visual Basic CreateResources.vb)文件中的以下代码创建一个名为 UIResources.resx 的 XML 资源文件,该文件存储表标题和一个 PersonTable 对象,其中包含为英语本地化的应用的信息。

using System;
using System.Resources;

public class CreateResource
{
   public static void Main()
   {
      PersonTable table = new PersonTable("Name", "Employee Number",
                                          "Age", 30, 18, 5);
      ResXResourceWriter rr = new ResXResourceWriter(@".\UIResources.resx");
      rr.AddResource("TableName", "Employees of Acme Corporation");
      rr.AddResource("Employees", table);
      rr.Generate();
      rr.Close();
   }
}
Imports System.Resources

Module CreateResource1
    Public Sub Main()
        Dim table As New PersonTable("Name", "Employee Number", "Age", 30, 18, 5)
        Dim rr As New ResXResourceWriter(".\UIResources.resx")
        rr.AddResource("TableName", "Employees of Acme Corporation")
        rr.AddResource("Employees", table)
        rr.Generate()
        rr.Close()
    End Sub
End Module

然后,GetObject.cs(或GetObject.vb)的源代码文件中的以下代码检索资源并将其显示在控制台中。

using System;
using System.Resources;

[assembly: NeutralResourcesLanguageAttribute("en")]

public class Example3
{
   public static void Main()
   {
      string fmtString = String.Empty;
      ResourceManager rm = new ResourceManager("UIResources", typeof(Example).Assembly);
      string title = rm.GetString("TableName");
      PersonTable tableInfo = (PersonTable) rm.GetObject("Employees");

      if (! String.IsNullOrEmpty(title)) {
         fmtString = "{0," + ((Console.WindowWidth + title.Length) / 2).ToString() + "}";
         Console.WriteLine(fmtString, title);
         Console.WriteLine();
      }

      for (int ctr = 1; ctr <= tableInfo.nColumns; ctr++) {
         string columnName = "column"  + ctr.ToString();
         string widthName = "width" + ctr.ToString();
         string value = tableInfo.GetType().GetField(columnName).GetValue(tableInfo).ToString();
         int width = (int) tableInfo.GetType().GetField(widthName).GetValue(tableInfo);
         fmtString = "{0,-" + width.ToString() + "}";
         Console.Write(fmtString, value);
      }
      Console.WriteLine();
   }
}
Imports System.Resources

<Assembly: NeutralResourcesLanguageAttribute("en")>

Module Example
   Public Sub Main()
      Dim fmtString As String = String.Empty
      Dim rm As New ResourceManager("UIResources", GetType(Example).Assembly)       
      Dim title As String = rm.GetString("TableName")
      Dim tableInfo As PersonTable = DirectCast(rm.GetObject("Employees"), PersonTable)

      If Not String.IsNullOrEmpty(title) Then
         fmtString = "{0," + ((Console.WindowWidth + title.Length) \ 2).ToString() + "}" 
         Console.WriteLine(fmtString, title)      
         Console.WriteLine()
      End If

      For ctr As Integer = 1 To tableInfo.nColumns
         Dim columnName As String = "column"  + ctr.ToString()
         Dim widthName As String = "width" + ctr.ToString()
         Dim value As String = CStr(tableInfo.GetType().GetField(columnName).GetValue(tableInfo))
         Dim width As Integer = CInt(tableInfo.GetType().GetField(widthName).GetValue(tableInfo))
         fmtString = "{0,-" + width.ToString() + "}"
         Console.Write(fmtString, value)
      Next      
      Console.WriteLine()
   End Sub
End Module

可以生成必要的资源文件和程序集,并通过执行以下批处理文件运行该应用。 必须使用 /r 选项提供具有对 UIElements.dll 的引用的 Resgen.exe,以便其能够访问有关 PersonTable 结构的信息。 如果使用 C#,请将 vbc 编译器名称替换为 csc,并将 .vb 扩展名替换为 .cs

vbc /t:library UIElements.vb
vbc CreateResources.vb /r:UIElements.dll
CreateResources

resgen UIResources.resx  /r:UIElements.dll
vbc GetObject.vb /r:UIElements.dll /resource:UIResources.resources

GetObject.exe

GetObject(String, CultureInfo) 方法

返回的资源针对指定的culture区域性或由属性指定的CultureInfo.CurrentUICulture区域性(如果culturenull为)进行本地化。 如果资源未针对该区域性进行本地化,资源管理器将使用回退规则来加载适当的资源。 如果未找到可用本地化资源集,资源管理器将回退到默认区域性的资源上。 如果未找到默认区域性的资源集,该方法将 MissingManifestResourceException 引发异常;如果预期资源集驻留在附属程序集中, MissingSatelliteAssemblyException 则引发异常。 如果资源管理器可以加载适当的资源集,但找不到名为 name的资源,该方法将 null返回。

示例

下面的示例使用 GetObject(String, CultureInfo) 方法反序列化一个自定义对象。 该示例包括一个名为NumberInfo.cs的源代码文件(如果使用的是 Visual Basic),该文件定义了以下名为 <NumberInfo.vb a0/> 的结构。 此结构旨在由一个简单的教育应用使用,该应用教授非英语学生以英语计算为 10。 请注意,该 Numbers 类使用 SerializableAttribute 特性进行标记。

using System;

[Serializable] public class Numbers2
{
   public readonly string One;
   public readonly string Two;
   public readonly string Three;
   public readonly string Four;
   public readonly string Five;
   public readonly string Six;
   public readonly string Seven;
   public readonly string Eight;
   public readonly string Nine;
   public readonly string Ten;

   public Numbers2(string one, string two, string three, string four, 
                  string five, string six, string seven, string eight,
                  string nine, string ten)
   {                     
      this.One = one;
      this.Two = two;
      this.Three = three;
      this.Four = four;
      this.Five = five;
      this.Six = six;
      this.Seven = seven;
      this.Eight = eight;
      this.Nine = nine;
      this.Ten = ten;                                    
   }                  
}
<Serializable> Public Class Numbers2
    Public ReadOnly One As String
    Public ReadOnly Two As String
    Public ReadOnly Three As String
    Public ReadOnly Four As String
    Public ReadOnly Five As String
    Public ReadOnly Six As String
    Public ReadOnly Seven As String
    Public ReadOnly Eight As String
    Public ReadOnly Nine As String
    Public ReadOnly Ten As String

    Public Sub New(one As String, two As String, three As String, four As String,
                   five As String, six As String, seven As String, eight As String,
                   nine As String, ten As String)
        Me.One = one
        Me.Two = two
        Me.Three = three
        Me.Four = four
        Me.Five = five
        Me.Six = six
        Me.Seven = seven
        Me.Eight = eight
        Me.Nine = nine
        Me.Ten = ten
    End Sub
End Class

名为 CreateResources.cs(CreateResources.vb for Visual Basic)的文件的以下源代码为默认英语以及法语、葡萄牙语和俄语创建 XML 资源文件。

using System;
using System.Resources;

public class CreateResource
{
   public static void Main()
   {
      Numbers en = new Numbers("one", "two", "three", "four", "five",
                               "six", "seven", "eight", "nine", "ten");
      CreateResourceFile(en, "en");
      Numbers fr = new Numbers("un", "deux", "trois", "quatre", "cinq", 
                               "six", "sept", "huit", "neuf", "dix");
      CreateResourceFile(fr, "fr");
      Numbers pt = new Numbers("um", "dois", "três", "quatro", "cinco", 
                               "seis", "sete", "oito", "nove", "dez");
      CreateResourceFile(pt, "pt"); 
      Numbers ru = new Numbers("один", "два", "три", "четыре", "пять", 
                               "шесть", "семь", "восемь", "девять", "десять");                                                       
      CreateResourceFile(ru, "ru");
   }

   public static void CreateResourceFile(Numbers n, string lang)
   {
      string filename = @".\NumberResources" + 
                        (lang != "en" ? "." + lang : "" ) +
                        ".resx";
      ResXResourceWriter rr = new ResXResourceWriter(filename);
      rr.AddResource("Numbers", n);
      rr.Generate();
      rr.Close();    
   }
}
Imports System.Resources

Module CreateResource
   Public Sub Main()
      Dim en As New Numbers("one", "two", "three", "four", "five",
                            "six", "seven", "eight", "nine", "ten")
      CreateResourceFile(en, "en")
      Dim fr As New Numbers("un", "deux", "trois", "quatre", "cinq", 
                            "six", "sept", "huit", "neuf", "dix")
      CreateResourceFile(fr, "fr")
      Dim pt As New Numbers("um", "dois", "três", "quatro", "cinco", 
                            "seis", "sete", "oito", "nove", "dez")
      CreateResourceFile(pt, "pt") 
      Dim ru As New Numbers("один", "два", "три", "четыре", "пять", 
                            "шесть", "семь", "восемь", "девять", "десять")                                                       
      CreateResourceFile(ru, "ru")
   End Sub

   Public Sub CreateResourceFile(n As Numbers, lang As String)
      Dim filename As String = ".\NumberResources" + 
                               If(lang <> "en", "." + lang, "") +
                               ".resx"
      Dim rr As New ResXResourceWriter(filename)
      rr.AddResource("Numbers", n)
      rr.Generate()
      rr.Close()    
   End Sub
End Module

资源由以下应用使用,它将当前 UI 区域性设置为法语(法国)、葡萄牙(巴西)或俄罗斯(俄罗斯)。 它调用 GetObject(String) 该方法以获取 Numbers 包含本地化数字的对象,以及 GetObject(String, CultureInfo) 获取 Numbers 包含英语语言数字的对象的方法。 然后,它使用当前 UI 区域性和英语显示奇数。 源代码文件命名为ShowNumbers.cs(ShowNumbers.vb)。

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

[assembly:NeutralResourcesLanguageAttribute("en-US")]

public class Example
{
   static string[] cultureNames = [ "fr-FR", "pt-BR", "ru-RU" ];

   public static void Main()
   {
      // Make any non-default culture the current culture.
      Random rnd = new Random();
      CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureNames[rnd.Next(0, cultureNames.Length)]);
      Thread.CurrentThread.CurrentUICulture = culture;
      Console.WriteLine("The current culture is {0}\n", CultureInfo.CurrentUICulture.Name);
      CultureInfo enCulture = CultureInfo.CreateSpecificCulture("en-US");

      ResourceManager rm = new ResourceManager(typeof(NumberResources));
      Numbers numbers = (Numbers) rm.GetObject("Numbers");
      Numbers numbersEn = (Numbers) rm.GetObject("Numbers", enCulture);
      Console.WriteLine("{0} --> {1}", numbers.One, numbersEn.One);
      Console.WriteLine("{0} --> {1}", numbers.Three, numbersEn.Three);
      Console.WriteLine("{0} --> {1}", numbers.Five, numbersEn.Five);
      Console.WriteLine("{0} --> {1}", numbers.Seven, numbersEn.Seven);
      Console.WriteLine("{0} --> {1}\n", numbers.Nine, numbersEn.Nine);
   }
}

internal class NumberResources
{
}
// The example displays output like the following:
//       The current culture is pt-BR
//
//       um --> one
//       três --> three
//       cinco --> five
//       sete --> seven
//       nove --> nine
Imports System.Globalization
Imports System.Resources
Imports System.Threading

Module Example2
    Dim cultureNames() As String = {"fr-FR", "pt-BR", "ru-RU"}

    Public Sub Main()
        ' Make any non-default culture the current culture.
        Dim rnd As New Random
        Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureNames(rnd.Next(0, cultureNames.Length)))
        Thread.CurrentThread.CurrentUICulture = culture
        Console.WriteLine("The current culture is {0}", CultureInfo.CurrentUICulture.Name)
        Console.WriteLine()
        Dim enCulture As CultureInfo = CultureInfo.CreateSpecificCulture("en-US")

        Dim rm As New ResourceManager(GetType(NumberResources))
        Dim numbers As Numbers = CType(rm.GetObject("Numbers"), Numbers)
        Dim numbersEn As Numbers = CType(rm.GetObject("Numbers", enCulture), Numbers)
        Console.WriteLine("{0} --> {1}", numbers.One, numbersEn.One)
        Console.WriteLine("{0} --> {1}", numbers.Three, numbersEn.Three)
        Console.WriteLine("{0} --> {1}", numbers.Five, numbersEn.Five)
        Console.WriteLine("{0} --> {1}", numbers.Seven, numbersEn.Seven)
        Console.WriteLine("{0} --> {1}", numbers.Nine, numbersEn.Nine)
        Console.WriteLine()
    End Sub
End Module


Friend Class NumberResources
End Class

' The example displays output like the following:
'       The current culture is pt-BR
'       
'       um --> one
'       três --> three
'       cinco --> five
'       sete --> seven
'       nove --> nine

可以使用以下批处理文件生成和执行示例的 Visual Basic 版本。 如果使用的是 C#,请替换为 vbccsc,并将扩展替换为 .vb.cs

vbc /t:library NumberInfo.vb

vbc CreateResources.vb /r:NumberInfo.dll
CreateResources

resgen NumberResources.resx /r:NumberInfo.dll

resgen NumberResources.fr.resx /r:Numberinfo.dll
Md fr
al /embed:NumberResources.fr.resources /culture:fr /t:lib /out:fr\ShowNumbers.resources.dll

resgen NumberResources.pt.resx  /r:Numberinfo.dll
Md pt
al /embed:NumberResources.pt.resources /culture:pt /t:lib /out:pt\ShowNumbers.resources.dll

resgen NumberResources.ru.resx /r:Numberinfo.dll
Md ru
al /embed:NumberResources.ru.resources /culture:ru /t:lib /out:ru\ShowNumbers.resources.dll

vbc ShowNumbers.vb /r:NumberInfo.dll /resource:NumberResources.resources
ShowNumbers.exe

性能注意事项

如果使用同一name参数多次调用GetObject该方法,则不依赖于返回对同一对象的引用的方法,每次调用。 这是因为该方法 GetObject 可以返回对缓存中现有资源对象的引用,也可以重新加载资源并返回对新资源对象的引用。