다음을 통해 공유


.NET 앱에서 리소스 검색

.NET 앱에서 지역화된 리소스를 사용하는 경우 기본 또는 중립 문화권에 대한 리소스를 주 어셈블리로 패키지하고 앱이 지원하는 각 언어 또는 문화권에 대해 별도의 위성 어셈블리를 만드는 것이 이상적입니다. 그런 다음 다음 섹션에서 설명한 ResourceManager 대로 클래스를 사용하여 명명된 리소스에 액세스할 수 있습니다. 주 어셈블리 및 위성 어셈블리에 리소스를 포함하지 않도록 선택하는 경우 이 문서의 뒷부분에 있는 .resources 파일에서 리소스 검색 섹션에 설명된 대로 이진 .resources 파일에 직접 액세스할 수도 있습니다.

어셈블리에서 리소스 검색

클래스는 ResourceManager 런타임에 리소스에 대한 액세스를 제공합니다. 메서드를 ResourceManager.GetString 사용하여 문자열 리소스를 검색하고 또는 ResourceManager.GetObject 메서드를 ResourceManager.GetStream 사용하여 문자열이 아닌 리소스를 검색합니다. 각 메서드에는 두 개의 오버로드가 있습니다.

  • 단일 매개 변수가 리소스의 이름을 포함하는 문자열인 오버로드입니다. 메서드는 현재 문화권에 대한 해당 리소스를 검색하려고 시도합니다. 자세한 내용은 GetString(String), GetObject(String), 및 GetStream(String) 메서드를 참조하세요.

  • 두 매개 변수가 있는 오버로드: 리소스의 이름을 포함하는 문자열 및 CultureInfo 리소스를 검색할 문화권을 나타내는 개체입니다. 해당 문화권에 대한 리소스 집합을 찾을 수 없는 경우 리소스 관리자는 대체 규칙을 사용하여 적절한 리소스를 검색합니다. 자세한 내용은 GetString(String, CultureInfo), GetObject(String, CultureInfo), 및 GetStream(String, CultureInfo) 메서드를 참조하세요.

리소스 관리자는 리소스 대체 프로세스를 사용하여 앱이 문화권별 리소스를 검색하는 방법을 제어합니다. 자세한 내용은 패키지 및 리소스 배포의 "리소스 대체 프로세스" 섹션을 참조하세요. 개체를 인스턴스화하는 ResourceManager 방법에 대한 자세한 내용은 클래스 항목의 "ResourceManager 개체 인스턴스화" 섹션을 ResourceManager 참조하세요.

문자열 데이터 검색 예제

다음 예제에서는 메서드를 GetString(String) 호출하여 현재 UI 문화권의 문자열 리소스를 검색합니다. 여기에는 영어(미국) 문화권에 대한 중립 문자열 리소스와 프랑스(프랑스) 및 러시아어(러시아) 문화권에 대한 지역화된 리소스가 포함됩니다. 다음 영어(미국) 리소스는 Strings.txt파일에 있습니다.

TimeHeader=The current time is

프랑스어(프랑스) 리소스는 Strings.fr-FR.txt파일에 있습니다.

TimeHeader=L'heure actuelle est

러시아(러시아) 리소스는 Strings.ru-RU.txt파일에 있습니다.

TimeHeader=Текущее время —

이 예제의 소스 코드는 C# 버전의 코드에 대한 GetString.cs 파일에 있고 Visual Basic 버전의 GetString.vb 리소스를 사용할 수 있는 세 문화권과 스페인어(스페인) 문화권이라는 네 가지 문화권의 이름을 포함하는 문자열 배열을 정의합니다. 5번 반복 실행되는 루프는 이러한 문화권 중 하나를 임의로 선택하고, 그 결과를 Thread.CurrentCultureCultureInfo.CurrentUICulture 속성에 할당합니다. 그런 다음 메서드를 GetString(String) 호출하여 현지화된 문자열을 검색합니다. 이 문자열은 하루 중 시간과 함께 표시됩니다.

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

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

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "fr-FR", "ru-RU", "es-ES" };
      Random rnd = new Random();
      ResourceManager rm = new ResourceManager("Strings",
                               typeof(Example).Assembly);

      for (int ctr = 0; ctr <= cultureNames.Length; ctr++) {
         string cultureName = cultureNames[rnd.Next(0, cultureNames.Length)];
         CultureInfo culture = CultureInfo.CreateSpecificCulture(cultureName);
         Thread.CurrentThread.CurrentCulture = culture;
         Thread.CurrentThread.CurrentUICulture = culture;

         Console.WriteLine($"Current culture: {culture.NativeName}");
         string timeString = rm.GetString("TimeHeader");
         Console.WriteLine($"{timeString} {DateTime.Now:T}\n");
      }
   }
}
// The example displays output like the following:
//    Current culture: English (United States)
//    The current time is 9:34:18 AM
//
//    Current culture: Español (España, alfabetización internacional)
//    The current time is 9:34:18
//
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18
//
//    Current culture: français (France)
//    L'heure actuelle est 09:34:18
//
//    Current culture: русский (Россия)
//    Текущее время — 9:34:18
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly: NeutralResourcesLanguageAttribute("en-US")>

Module Example
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "fr-FR", "ru-RU", "es-ES"}
        Dim rnd As New Random()
        Dim rm As New ResourceManager("Strings", GetType(Example).Assembly)

        For ctr As Integer = 0 To cultureNames.Length
            Dim cultureName As String = cultureNames(rnd.Next(0, cultureNames.Length))
            Dim culture As CultureInfo = CultureInfo.CreateSpecificCulture(cultureName)
            Thread.CurrentThread.CurrentCulture = culture
            Thread.CurrentThread.CurrentUICulture = culture

            Console.WriteLine("Current culture: {0}", culture.NativeName)
            Dim timeString As String = rm.GetString("TimeHeader")
            Console.WriteLine("{0} {1:T}", timeString, Date.Now)
            Console.WriteLine()
        Next
    End Sub
End Module
' The example displays output similar to the following:
'    Current culture: English (United States)
'    The current time is 9:34:18 AM
'    
'    Current culture: Español (España, alfabetización internacional)
'    The current time is 9:34:18
'    
'    Current culture: русский (Россия)
'    Текущее время — 9:34:18
'    
'    Current culture: français (France)
'    L'heure actuelle est 09:34:18
'    
'    Current culture: русский (Россия)
'    Текущее время — 9:34:18

다음 일괄 처리(.bat) 파일은 예제를 컴파일하고 적절한 디렉터리에 위성 어셈블리를 생성합니다. C# 언어 및 컴파일러에 대한 명령이 제공됩니다. Visual Basic의 경우 cscvbc으로 변경하고, GetString.csGetString.vb으로 변경합니다.

resgen strings.txt
csc GetString.cs -resource:strings.resources

resgen strings.fr-FR.txt
md fr-FR
al -embed:strings.fr-FR.resources -culture:fr-FR -out:fr-FR\GetString.resources.dll

resgen strings.ru-RU.txt
md ru-RU
al -embed:strings.ru-RU.resources -culture:ru-RU -out:ru-RU\GetString.resources.dll

현재 UI 문화권이 스페인어(스페인)인 경우 스페인어 리소스를 사용할 수 없으며 영어가 예제의 기본 문화권이므로 예제에 영어 리소스가 표시됩니다.

개체 데이터 검색 예제

GetObjectGetStream 메서드를 사용하여 개체 데이터를 검색할 수 있습니다. 여기에는 기본 데이터 형식, 직렬화 가능한 개체 및 이진 형식(예: 이미지)으로 저장된 개체가 포함됩니다.

다음 예제에서는 이 메서드를 사용하여 GetStream(String) 앱의 시작 창을 여는 데 사용되는 비트맵을 검색합니다. CreateResources.cs(C#) 또는 CreateResources.vb(Visual Basic의 경우)라는 파일의 다음 소스 코드는 직렬화된 이미지를 포함하는 .resx 파일을 생성합니다. 이 경우 이미지가 SplashScreen.jpg; 파일에서 로드됩니다. 파일 이름을 수정하여 자신의 이미지를 대체할 수 있습니다.

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Resources;

public class Example
{
   public static void Main()
   {
      Bitmap bmp = new Bitmap(@".\SplashScreen.jpg");
      MemoryStream imageStream = new MemoryStream();
      bmp.Save(imageStream, ImageFormat.Jpeg);

      ResXResourceWriter writer = new ResXResourceWriter("AppResources.resx");
      writer.AddResource("SplashScreen", imageStream);
      writer.Generate();
      writer.Close();
   }
}
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.IO
Imports System.Resources

Module Example
    Public Sub Main()
        Dim bmp As New Bitmap(".\SplashScreen.jpg")
        Dim imageStream As New MemoryStream()
        bmp.Save(imageStream, ImageFormat.Jpeg)

        Dim writer As New ResXResourceWriter("AppResources.resx")
        writer.AddResource("SplashScreen", imageStream)
        writer.Generate()
        writer.Close()
    End Sub
End Module

다음 코드는 리소스를 검색하고 컨트롤에 PictureBox 이미지를 표시합니다.

using System;
using System.Drawing;
using System.IO;
using System.Resources;
using System.Windows.Forms;

public class Example
{
   public static void Main()
   {
      ResourceManager rm = new ResourceManager("AppResources", typeof(Example).Assembly);
      Bitmap screen = (Bitmap) Image.FromStream(rm.GetStream("SplashScreen"));

      Form frm = new Form();
      frm.Size = new Size(300, 300);

      PictureBox pic = new PictureBox();
      pic.Bounds = frm.RestoreBounds;
      pic.BorderStyle = BorderStyle.Fixed3D;
      pic.Image = screen;
      pic.SizeMode = PictureBoxSizeMode.StretchImage;

      frm.Controls.Add(pic);
      pic.Anchor = AnchorStyles.Top | AnchorStyles.Bottom |
                   AnchorStyles.Left | AnchorStyles.Right;

      frm.ShowDialog();
   }
}
Imports System.Drawing
Imports System.IO
Imports System.Resources
Imports System.Windows.Forms

Module Example
    Public Sub Main()
        Dim rm As New ResourceManager("AppResources", GetType(Example).Assembly)
        Dim screen As Bitmap = CType(Image.FromStream(rm.GetStream("SplashScreen")), Bitmap)

        Dim frm As New Form()
        frm.Size = new Size(300, 300)

        Dim pic As New PictureBox()
        pic.Bounds = frm.RestoreBounds
        pic.BorderStyle = BorderStyle.Fixed3D
        pic.Image = screen
        pic.SizeMode = PictureBoxSizeMode.StretchImage

        frm.Controls.Add(pic)
        pic.Anchor = AnchorStyles.Top Or AnchorStyles.Bottom Or
                     AnchorStyles.Left Or AnchorStyles.Right

        frm.ShowDialog()
    End Sub
End Module

다음 일괄 처리 파일을 사용하여 C# 예제를 빌드할 수 있습니다. Visual Basic의 경우 cscvbc변경하고 소스 코드 파일의 확장명은 .cs.vb변경합니다.

csc CreateResources.cs
CreateResources

resgen AppResources.resx

csc GetStream.cs -resource:AppResources.resources

다음 예제에서는 메서드를 ResourceManager.GetObject(String) 사용하여 사용자 지정 개체를 역직렬화합니다. 이 예제에는 다음 구조체를 정의하는 UIElements.cs(Visual Basic용 UIElements.vb)라는 소스 코드 파일이 포함되어 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 PersonTable
    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)라는 파일의 다음 코드는 테이블 제목과 PersonTable 영어로 지역화된 앱에 대한 정보를 포함하는 개체를 저장하는 UIResources.resx라는 XML 리소스 파일을 만듭니다.

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 CreateResource
    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.vb(GetObject.cs)라는 소스 코드 파일의 다음 코드는 리소스를 검색하여 콘솔에 표시합니다.

using System;
using System.Resources;

[assembly: NeutralResourcesLanguageAttribute("en")]

public class Example
{
   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

위성 어셈블리에 대한 버전 지원

기본적으로 개체는 ResourceManager 요청된 리소스를 검색할 때 주 어셈블리의 버전 번호와 일치하는 버전 번호가 있는 위성 어셈블리를 찾습니다. 앱을 배포한 후 주 어셈블리 또는 특정 리소스 위성 어셈블리를 업데이트할 수 있습니다. .NET Framework는 주 어셈블리 및 위성 어셈블리의 버전 관리 지원을 제공합니다.

이 특성은 SatelliteContractVersionAttribute 주 어셈블리에 대한 버전 관리 지원을 제공합니다. 앱의 주 어셈블리에서 이 특성을 지정하면 위성 어셈블리를 업데이트하지 않고 주 어셈블리를 업데이트하고 다시 배포할 수 있습니다. 주 어셈블리를 업데이트한 후 주 어셈블리의 버전 번호를 증가하지만 위성 계약 버전 번호는 변경되지 않은 상태로 둡니다. 리소스 관리자는 요청된 리소스를 검색할 때 이 특성에 지정된 위성 어셈블리 버전을 로드합니다.

게시자 정책 어셈블리는 위성 어셈블리의 버전 관리 지원을 제공합니다. 주 어셈블리를 업데이트하지 않고 위성 어셈블리를 업데이트하고 다시 배포할 수 있습니다. 위성 어셈블리를 업데이트한 후 해당 버전 번호를 증가시키고 게시자 정책 어셈블리와 함께 제공합니다. 게시자 정책 어셈블리에서 새 위성 어셈블리가 이전 버전과 호환되도록 지정합니다. 리소스 관리자는 특성을 사용하여 SatelliteContractVersionAttribute 위성 어셈블리의 버전을 결정하지만 어셈블리 로더는 게시자 정책에 지정된 위성 어셈블리 버전에 바인딩됩니다. 게시자 정책 어셈블리에 대한 자세한 내용은 게시자 정책 파일 만들기를 참조하세요.

전체 어셈블리 버전 관리 지원을 사용하도록 설정하려면 전역 어셈블리 캐시 에 강력한 이름의 어셈블리를 배포하고 애플리케이션 디렉터리에 강력한 이름이 없는 어셈블리를 배포하는 것이 좋습니다. 애플리케이션 디렉터리에 강력한 이름의 어셈블리를 배포하려는 경우 어셈블리를 업데이트할 때 위성 어셈블리의 버전 번호를 증가시킬 수 없습니다. 대신 기존 코드를 업데이트된 코드로 바꾸고 동일한 버전 번호를 유지 관리하는 현재 위치 업데이트를 수행해야 합니다. 예를 들어 위성 어셈블리의 버전 1.0.0.0을 완전히 지정된 어셈블리 이름으로 업데이트하려면 "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a", 완전히 지정된 동일한 어셈블리 이름 "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a"로 컴파일된 업데이트된 myApp.resources.dll 덮어씁니다. 위성 어셈블리 파일에서 현재 위치 업데이트를 사용하면 앱에서 위성 어셈블리의 버전을 정확하게 확인하기가 어렵습니다.

어셈블리 버전 관리에 대한 자세한 내용은 어셈블리 버전 관리런타임에서 어셈블리를 찾는 방법을 참조하세요.

.resources 파일에서 리소스 검색

위성 어셈블리에 리소스를 배포하지 않도록 선택한 경우에도 개체를 ResourceManager 사용하여 .resources 파일의 리소스에 직접 액세스할 수 있습니다. 이렇게 하려면 .resources 파일을 올바르게 배포해야 합니다. 그런 다음 이 메서드를 ResourceManager.CreateFileBasedResourceManager 사용하여 개체를 ResourceManager 인스턴스화하고 독립 실행형 .resources 파일이 포함된 디렉터리를 지정합니다.

.resources 파일 배포

애플리케이션 어셈블리 및 위성 어셈블리에 .resources 파일을 포함하는 경우 각 위성 어셈블리의 파일 이름은 같지만 위성 어셈블리의 문화권을 반영하는 하위 디렉터리에 배치됩니다. 반면. .resources 파일에서 리소스에 직접 액세스하는 경우 모든 .resources 파일을 단일 디렉터리(일반적으로 애플리케이션 디렉터리의 하위 디렉터리)에 배치할 수 있습니다. 앱의 기본 .resources 파일 이름은 문화권(예: strings.resources)을 표시하지 않고 루트 이름으로만 구성됩니다. 지역화된 각 문화권의 리소스는 파일에 저장되며, 이 파일의 이름은 루트 이름에 문화권을 덧붙여 구성됩니다(예: strings.ja.resources 또는 strings.de-DE.resources).

다음 그림에서는 디렉터리 구조에서 리소스 파일을 배치해야 하는 위치를 보여 줍니다. 또한 .resource 파일에 대한 명명 규칙도 제공합니다.

애플리케이션의 주 디렉터리를 보여 주는 일러스트레이션.

리소스 관리자 사용

리소스를 만들고 적절한 디렉터리에 배치한 후에는 메서드를 ResourceManager 호출하여 리소스를 사용할 개체를 CreateFileBasedResourceManager(String, String, Type) 만듭니다. 첫 번째 매개 변수는 앱의 기본 .resources 파일의 루트 이름을 지정합니다(이전 섹션의 예제에 대한 "문자열"). 두 번째 매개 변수는 리소스의 위치(이전 예제의 "리소스")를 지정합니다. 세 번째 매개 변수는 사용할 구현을 ResourceSet 지정합니다. 세 번째 매개 변수인 null경우 기본 런타임 ResourceSet 이 사용됩니다.

비고

독립 실행형 .resources 파일을 사용하여 ASP.NET 앱을 배포하지 마세요. 이로 인해 잠금 문제가 발생하고 XCOPY 배포가 중단될 수 있습니다. 위성 어셈블리에 ASP.NET 리소스를 배포하는 것이 좋습니다. 자세한 내용은 ASP.NET 웹 페이지 리소스 개요를 참조하세요.

ResourceManager 개체를 인스턴스화한 후, 앞에서 설명한 대로 리소스를 검색하기 위해 GetString, GetObject, 및 GetStream 메서드를 사용합니다. 그러나 .resources 파일에서 직접 리소스를 검색하는 것은 어셈블리에서 포함된 리소스를 검색하는 것과 다릅니다. .resources 파일에서 리소스를 검색할 때, GetString(String), GetObject(String), GetStream(String) 메서드는 현재 문화권과 관계없이 항상 기본 문화권의 리소스를 검색합니다. 앱의 현재 문화권 또는 특정 문화권의 리소스를 검색하려면 , GetString(String, CultureInfo)또는 GetObject(String, CultureInfo) 메서드를 호출GetStream(String, CultureInfo)하고 리소스를 검색할 문화권을 지정해야 합니다. 현재 문화권의 리소스를 검색하려면 속성 값을 CultureInfo.CurrentCulture 인수로 culture 지정합니다. 리소스 관리자가 리소스 culture를 검색할 수 없는 경우 표준 리소스 대체 규칙을 사용하여 적절한 리소스를 검색합니다.

예제

다음 예제에서는 리소스 관리자가 .resources 파일에서 직접 리소스를 검색하는 방법을 보여 줍니다. 이 예제는 영어(미국), 프랑스어(프랑스) 및 러시아어(러시아) 문화권에 대한 세 개의 텍스트 기반 리소스 파일로 구성됩니다. 영어(미국)는 예제의 기본 문화권입니다. 해당 리소스는 Strings.txt다음 파일에 저장됩니다.

Greeting=Hello
Prompt=What is your name?

프랑스어(프랑스) 문화권에 대한 리소스는 Strings.fr-FR.txt이름이 지정된 다음 파일에 저장됩니다.

Greeting=Bon jour
Prompt=Comment vous appelez-vous?

러시아어(러시아) 문화권에 대한 리소스는 Strings.ru-RU.txt이름이 지정된 다음 파일에 저장됩니다.

Greeting=Здравствуйте
Prompt=Как вас зовут?

다음은 예제의 소스 코드입니다. 이 예제에서는 영어(미국), 영어(캐나다), 프랑스어(프랑스) 및 러시아어(러시아) 문화권에 대한 개체를 인스턴스화 CultureInfo 하고 각각 현재 문화권을 만듭니다. 그런 다음 ResourceManager.GetString(String, CultureInfo) 메서드는 CultureInfo.CurrentCulture 속성 값을 culture 인수로 제공하여 적절한 문화권별 리소스를 검색합니다.

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

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

public class Example
{
   public static void Main()
   {
      string[] cultureNames = { "en-US", "en-CA", "ru-RU", "fr-FR" };
      ResourceManager rm = ResourceManager.CreateFileBasedResourceManager("Strings", "Resources", null);

      foreach (var cultureName in cultureNames) {
         Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
         string greeting = rm.GetString("Greeting", CultureInfo.CurrentCulture);
         Console.WriteLine($"\n{greeting}!");
         Console.Write(rm.GetString("Prompt", CultureInfo.CurrentCulture));
         string name = Console.ReadLine();
         if (! String.IsNullOrEmpty(name))
            Console.WriteLine("{0}, {1}!", greeting, name);
      }
      Console.WriteLine();
   }
}
// The example displays output like the following:
//       Hello!
//       What is your name? Dakota
//       Hello, Dakota!
//
//       Hello!
//       What is your name? Koani
//       Hello, Koani!
//
//       Здравствуйте!
//       Как вас зовут?Samuel
//       Здравствуйте, Samuel!
//
//       Bon jour!
//       Comment vous appelez-vous?Yiska
//       Bon jour, Yiska!
Imports System.Globalization
Imports System.Resources
Imports System.Threading

<Assembly: NeutralResourcesLanguageAttribute("en-US")>

Module Example
    Public Sub Main()
        Dim cultureNames() As String = {"en-US", "en-CA", "ru-RU", "fr-FR"}
        Dim rm As ResourceManager = ResourceManager.CreateFileBasedResourceManager("Strings", "Resources", Nothing)

        For Each cultureName In cultureNames
            Console.WriteLine()
            Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
            Dim greeting As String = rm.GetString("Greeting", CultureInfo.CurrentCulture)
            Console.WriteLine("{0}!", greeting)
            Console.Write(rm.GetString("Prompt", CultureInfo.CurrentCulture))
            Dim name As String = Console.ReadLine()
            If Not String.IsNullOrEmpty(name) Then
                Console.WriteLine("{0}, {1}!", greeting, name)
            End If
        Next
        Console.WriteLine()
    End Sub
End Module
' The example displays output like the following:
'       Hello!
'       What is your name? Dakota
'       Hello, Dakota!
'       
'       Hello!
'       What is your name? Koani
'       Hello, Koani!
'       
'       Здравствуйте!
'       Как вас зовут?Samuel
'       Здравствуйте, Samuel!
'       
'       Bon jour!
'       Comment vous appelez-vous?Yiska
'       Bon jour, Yiska!

다음 일괄 처리 파일을 실행하여 예제의 C# 버전을 컴파일할 수 있습니다. Visual Basic을 사용하는 경우 cscvbc로 바꾸고, .cs 확장을 .vb로 바꾸세요.

md Resources
resgen Strings.txt Resources\Strings.resources
resgen Strings.fr-FR.txt Resources\Strings.fr-FR.resources
resgen Strings.ru-RU.txt Resources\Strings.ru-RU.resources

csc Example.cs

참고하십시오