Методы System.Resources.ResourceManager.GetObject
В этой статье приводятся дополнительные замечания к справочной документации по этому API.
Метод GetObject используется для извлечения нестроковых ресурсов. К ним относятся значения, относящиеся к примитивным типам данных, таким как Int32 или Doubleрастровые изображения (например System.Drawing.Bitmap , объект) или пользовательским сериализованным объектам. Как правило, возвращаемый объект должен быть приведение (в C#) или преобразован (в Visual Basic) в объект соответствующего типа.
Свойство IgnoreCase определяет, учитывается ли сравнение name
с именами ресурсов без учета регистра или регистра (по умолчанию).
Примечание.
Эти методы могут вызывать больше исключений, чем перечислены. Одна из причин, по которой может произойти, заключается в том, что метод, вызывающий этот метод, вызывает исключение. Например, FileLoadException исключение может возникать, если произошла ошибка при развертывании или установке вспомогательной сборки, или SerializationException может возникать исключение, если определяемый пользователем тип создает определяемое пользователем исключение при десериализации типа.
GetObject(String)Метод
Возвращаемый ресурс локализован для языка и региональных параметров пользовательского интерфейса текущего потока, который определяется свойством CultureInfo.CurrentUICulture . Если ресурс не локализован для этого языка и региональных параметров, диспетчер ресурсов использует резервные правила для загрузки соответствующего ресурса. Если не найден доступный набор локализованных ресурсов, ResourceManager возвращается к ресурсам языка и региональных параметров по умолчанию. Если набор ресурсов для языка и региональных параметров по умолчанию не найден, метод создает MissingManifestResourceException исключение или, если набор ресурсов, как ожидается, находится в вспомогательной сборке, MissingSatelliteAssemblyException исключение. Если диспетчер ресурсов может загрузить соответствующий набор ресурсов, но не может найти именованный name
ресурс, метод возвращается null
.
Пример
В следующем примере для десериализации настраиваемого объекта используется метод GetObject(String) . В примере содержится файл исходного кода с именем UIElements.cs (UIElements.vb, если вы используете Visual Basic), который определяет следующую структуру с именем PersonTable
. Эта структура предназначена для использования подпрограммой общего отображения таблиц, которая отображает локализованные имена для столбцов таблиц. Обратите внимание, что структура 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 (или CreateResources.vb для Visual Basic) создает XML-файл ресурсов с именем UIResources.resx, который хранит заголовок таблицы и 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
, чтобы предоставить Resgen.exe ссылку на UIElements.dll для доступа к информации о структуре 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 , если culture
имеет значение null
. Если ресурс не локализован для этого языка и региональных параметров, диспетчер ресурсов использует резервные правила для загрузки соответствующего ресурса. Если не найден доступный набор локализованных ресурсов, диспетчер ресурсов возвращает ресурсы языка и региональных параметров по умолчанию. Если набор ресурсов для языка и региональных параметров по умолчанию не найден, метод создает MissingManifestResourceException исключение или, если набор ресурсов, как ожидается, находится в вспомогательной сборке, MissingSatelliteAssemblyException исключение. Если диспетчер ресурсов может загрузить соответствующий набор ресурсов, но не может найти именованный name
ресурс, метод возвращается null
.
Пример
В следующем примере для десериализации настраиваемого объекта используется метод GetObject(String, CultureInfo) . В этом примере содержится файл исходного кода с именем NumberInfo.cs (NumberInfo.vb, если вы используете Visual Basic), который определяет следующую структуру с именем Numbers
. Эта структура предназначена для использования простым учебным приложением, которое учит студентов, не говорящих на английском языке, для подсчета до десяти на английском языке. Обратите внимание, что 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 для 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
Ресурсы используются следующим приложением, которое задает для текущего языка и региональных параметров пользовательского интерфейса французский (Франция), португальский (Бразилия) или русский (Россия). Он вызывает GetObject(String) метод для получения объекта, содержащего локализованные числа, и GetObject(String, CultureInfo) метод для получения Numbers
Numbers
объекта, содержащего номера английского языка. Затем отображаются нечетные числа с использованием текущего языка и языка пользовательского интерфейса. Файл исходного кода называется 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#, замените vbc
его csc
и замените .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
Замечания, связанные с быстродействием
Если метод вызывается GetObject несколько раз с name
тем же параметром, не зависит от метода, возвращающего ссылку на один и тот же объект с каждым вызовом. Это связано с тем, что GetObject метод может возвращать ссылку на существующий объект ресурса в кэше или может перезагрузить ресурс и вернуть ссылку на новый объект ресурса.