Recuperare le risorse nelle app .NET

Quando si usano risorse localizzate nelle app .NET, è consigliabile creare un pacchetto delle risorse per le impostazioni cultura predefinite o non associate ad alcun paese con l'assembly principale e un assembly satellite separato per ogni lingua o impostazione cultura supportata dall'app. È quindi possibile utilizzare la classe ResourceManager come descritto nella sezione successiva per accedere alle risorse denominate. Se si sceglie di non incorporare le risorse nell'assembly principale e negli assembly satellite, è anche possibile accedere direttamente ai file binari con estensione .resources, come illustrato nella sezione Recuperare risorse da file .resources più avanti in questo articolo.

Recuperare risorse dagli assembly

La classe ResourceManager fornisce l'accesso alle risorse in fase di esecuzione. Utilizzare il metodo ResourceManager.GetString per recuperare le risorse di tipo stringa e il metodo ResourceManager.GetObject o ResourceManager.GetStream per recuperare le risorse non di tipo stringa. Ogni metodo dispone di due overload:

  • Un overload di cui l'unico parametro è una stringa contenente il nome della risorsa. Il metodo tenta di recuperare la risorsa per le impostazioni cultura correnti. Per ulteriori informazioni, vedere i metodi GetString(String), GetObject(String) e GetStream(String).

  • Un overload che dispone di due parametri: una stringa contenente il nome della risorsa e un oggetto CultureInfo che rappresenta le impostazioni cultura di cui deve essere recuperata la risorsa. Se non è possibile trovare un set di risorse per le impostazioni cultura, il gestore di risorse utilizza le regole di fallback per recuperare una risorsa appropriata. Per ulteriori informazioni, vedere i metodi GetString(String, CultureInfo), GetObject(String, CultureInfo) e GetStream(String, CultureInfo).

Il gestore di risorse utilizza il processo di fallback delle risorse per controllare come l'applicazione recupera le risorse specifiche delle impostazioni cultura. Per altre informazioni, vedere la sezione "Processo di fallback delle risorse" in Creare pacchetti e distribuire risorse. Per informazioni sulla creazione di un'istanza di un oggetto ResourceManager , vedere la sezione "Creazione di un'istanza di un oggetto ResourceManager" nell'argomento relativo alla classe ResourceManager .

Esempio di recupero di dati stringa

Nell'esempio seguente viene chiamato il metodo GetString(String) per recuperare le risorse di tipo stringa delle impostazioni cultura correnti dell'interfaccia utente. Include una risorsa di tipo stringa non associata ad alcun paese per le impostazioni cultura inglesi (Stati Uniti) e le risorse localizzate per le impostazioni cultura francesi (Francia) e russe (Russia). La risorsa inglese (Stati Uniti) seguente si trova in un file denominato Strings.txt:

TimeHeader=The current time is

La risorsa francese (Francia) si trova in un file denominato Strings.fr-FR.txt:

TimeHeader=L'heure actuelle est

La risorsa russa (Russia) si trova in un file denominato Strings.ru-RU-txt:

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

Il codice sorgente per questo esempio, che si trova in un file denominato GetString.cs per la versione C# del codice e GetString.vb per la versione Visual Basic, definisce una matrice di stringhe contenente il nome di quattro impostazioni cultura: le tre impostazioni cultura per le quali sono disponibili le risorse e le impostazioni cultura spagnole (Spagna). Un ciclo eseguibile cinque volte seleziona casualmente una di queste impostazioni cultura e la assegna alle proprietà Thread.CurrentCulture e CultureInfo.CurrentUICulture . Chiama quindi il metodo GetString(String) per recuperare la stringa localizzata, visualizzata con l'ora del giorno.

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: {0}", culture.NativeName);
         string timeString = rm.GetString("TimeHeader");
         Console.WriteLine("{0} {1:T}\n", timeString, DateTime.Now);
      }
   }
}
// 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

Il seguente file batch (.bat) consente di compilare l'esempio e genera gli assembly satellite nelle directory appropriate. I comandi vengono forniti per il linguaggio e il compilatore C#. Per Visual Basic, modificare csc in vbce modificare GetString.cs in GetString.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

Quando le impostazioni cultura correnti dell'interfaccia utente sono impostate sullo spagnolo (Spagna), si noti che nell'esempio vengono visualizzate le risorse della lingua inglese, perché le risorse della lingua spagnola non sono disponibili e l'inglese rappresenta le impostazioni cultura predefinite dell'esempio.

Esempi di recupero di dati oggetto

È possibile utilizzare i metodi GetObject e GetStream per recuperare i dati oggetto. Sono inclusi i tipi di dati primitivi, gli oggetti serializzabili e gli oggetti archiviati in formato binario, ad esempio le immagini.

Nell'esempio seguente viene usato il metodo GetStream(String) per recuperare una bitmap visualizzata nella finestra iniziale di apertura di un'app. Il seguente codice sorgente in un file denominato CreateResources.cs (per C#) o CreateResources.vb (per Visual Basic) genera un file .resx che contiene l'immagine serializzata. In questo caso, l'immagine viene caricata da un file denominato SplashScreen.jpg. È possibile modificare il nome per sostituire il file con un'immagine personalizzata.

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

Il seguente codice recupera la risorsa e visualizza l'immagine in un controllo 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

È possibile usare il file batch seguente per compilare l'esempio in C#. Per Visual Basic, sostituire csc con vbce modificare l'estensione del file del codice sorgente da .cs a .vb.

csc CreateResources.cs
CreateResources

resgen AppResources.resx

csc GetStream.cs -resource:AppResources.resources

Nell'esempio seguente viene usato il metodo ResourceManager.GetObject(String) per deserializzare un oggetto personalizzato. L'esempio include un file di codice sorgente denominato UIElements.cs (UIElements.vb per Visual Basic) che definisce la seguente struttura denominata PersonTable. Questa struttura deve essere usata da una procedura generale di visualizzazione della tabella che mostra i nomi localizzati delle colonne della tabella. Si noti che la struttura PersonTable è contrassegnata con l'attributo 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

Il codice seguente, proveniente da un file denominato CreateResources.cs (CreateResources.vb per Visual Basic), crea un file di risorse XML denominato UIResources.resx che memorizza un titolo di tabella e un oggetto PersonTable contenente le informazioni per un'app che viene localizzata per la lingua inglese.

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

Il codice seguente, contenuto in un file di codice sorgente denominato GetObject.cs (GetObject.vb), recupera quindi le risorse e le visualizza nella console.

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

È possibile creare il file di risorse e gli assembly necessari ed eseguire l'app mediante il file batch seguente. È necessario usare l'opzione /r per fornire a Resgen.exe un riferimento a UIElements.dll in modo che possa accedere alle informazioni sulla struttura PersonTable . Se si usa C#, sostituire il nome del compilatore vbc con csce l'estensione .vb con .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

Supporto della versione per gli assembly satellite

Per impostazione predefinita, quando l'oggetto ResourceManager recupera le risorse richieste, cerca gli assembly satellite con numeri di versione che corrispondono a quello dell'assembly principale. Una volta distribuita un'applicazione, è possibile che si desideri aggiornare l'assembly principale o gli assembly satellite di risorse specifiche. .NET Framework offre supporto per il controllo delle versioni dell'assembly principale e degli assembly satellite.

L'attributo SatelliteContractVersionAttribute fornisce supporto per il controllo delle versioni di un assembly principale. Specificare questo attributo per l'assembly principale di un'applicazione consente di aggiornare e ridistribuire un assembly principale senza aggiornare i relativi assembly satellite. Una volta aggiornato l'assembly principale, incrementare il numero di versione dell'assembly principale, ma lasciare inalterato il numero di versione del contratto con i satelliti. Per recuperare le risorse richieste, il gestore di risorse carica la versione di assembly satellite specificata da questo attributo.

Gli assembly di criteri dell'editore forniscono il supporto per il controllo delle versioni degli assembly satellite. È possibile aggiornare e ridistribuire un assembly satellite senza aggiornare l'assembly principale. Una volta aggiornato un assembly satellite, incrementarne il numero di versione e fornirlo con un assembly di criteri dell'editore. Nell'assembly di criteri dell'editore specificare che il nuovo assembly satellite è compatibile con le versioni precedenti. Il gestore di risorse utilizzerà l'attributo SatelliteContractVersionAttribute per determinare la versione di assembly satellite, ma il caricatore di assembly verrà associato alla versione di assembly satellite specificata dai criteri editore. Per altre informazioni sugli assembly di criteri dell'editore, vedere Creare un file dei criteri dell’editore.

Per abilitare il supporto completo del controllo delle versioni, si consiglia di distribuire gli assembly con nome sicuro nella Global Assembly Cache e gli assembly che non hanno nome sicuro nella directory dell'applicazione. Se si vuole distribuire assembly con nome sicuro nella directory dell'applicazione, non sarà possibile incrementare il numero di versione di un assembly satellite quando si aggiorna l'assembly. Sarà invece necessario eseguire un aggiornamento sul posto in base al quale il codice esistente verrà sostituito dal codice aggiornato e verrà mantenuto lo stesso numero di versione. Se, ad esempio, si desidera aggiornare la versione 1.0.0.0 di un assembly satellite con il nome assembly completo "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a", sovrascriverlo con il file myApp.resources.dll aggiornato compilato con lo stesso nome assembly completo "myApp.resources, Version=1.0.0.0, Culture=de, PublicKeyToken=b03f5f11d50a3a". Si noti che l'utilizzo degli aggiornamenti sul posto dei file di assembly satellite rende difficile la determinazione accurata da parte dell'applicazione della versione di un assembly satellite.

Per altre informazioni sul controllo delle versioni degli assembly, vedere Controllo delle versioni degli assembly e Come il runtime individua gli assembly.

Recuperare risorse da file .resources

Se si sceglie di non distribuire le risorse in assembly satellite, è comunque possibile utilizzare direttamente un oggetto ResourceManager per accedere alle risorse dai file .resources. A tale scopo, è necessario distribuire i file .resources correttamente. Utilizzare quindi il metodo ResourceManager.CreateFileBasedResourceManager per creare un'istanza di un oggetto ResourceManager e specificare la directory contenente i file .resources autonomi.

Distribuire file .resources

Quando si incorporano i file .resources in un assembly dell'applicazione e in assembly satellite, ogni assembly satellite ha lo stesso nome file, ma viene collocato in una sottodirectory che corrisponde alle impostazioni cultura dell'assembly satellite. Al contrario, quando si accede direttamente alle risorse dai file .resources, è possibile inserire tutti i file .resources in una singola directory, in genere una sottodirectory della directory dell'applicazione. Il nome del file .resources predefinito dell'applicazione è costituito solo da un nome radice, senza indicare le impostazioni cultura, ad esempio strings.resources. Le risorse per ogni impostazione cultura localizzata vengono archiviate in un file il cui nome è costituito dal nome radice seguito dalle impostazioni cultura, ad esempio strings.ja.resources o strings.de-DE.resources.

La figura seguente mostra dove collocare i file di risorse nella struttura di directory. Illustra anche le convenzioni di denominazione per i file di risorse.

Illustration that shows the main directory for your application.

Usare la gestione risorse

Dopo aver creato e inserito le risorse nella directory appropriata, creare un oggetto ResourceManager per utilizzare le risorse chiamando il metodo CreateFileBasedResourceManager(String, String, Type) . Il primo parametro specifica il nome radice del file .resources predefinito dell'applicazione, ovvero "stringa" per l'esempio nella sezione precedente. Il secondo parametro specifica il percorso delle risorse, ovvero "Resources" per l'esempio precedente. Il terzo parametro specifica l'implementazione di ResourceSet da usare. Se il terzo parametro è null, viene utilizzato il runtime predefinito ResourceSet .

Nota

Non distribuire applicazioni ASP.NET utilizzando file .resources autonomi. Questo può causare problemi di blocco e interrompere la distribuzione XCOPY. Si consiglia di distribuire le risorse ASP.NET in assembly satellite. Per altre informazioni, vedere Cenni preliminari sulle risorse delle pagine Web ASP.NET.

Dopo avere creato un'istanza dell'oggetto ResourceManager , utilizzare i metodi GetString, GetObjecte GetStream come illustrato in precedenza per recuperare le risorse. Tuttavia, il recupero delle risorse direttamente dai file .resources differisce dal recupero delle risorse incorporate dagli assembly. Quando si recuperano le risorse dai file .resources, i metodi GetString(String), GetObject(String)e GetStream(String) recuperano sempre le risorse delle impostazioni cultura predefinite indipendentemente dalle impostazioni cultura correnti. Per recuperare le risorse delle impostazioni cultura correnti dell'applicazione o di impostazioni cultura specifiche, è necessario chiamare il metodo GetString(String, CultureInfo), GetObject(String, CultureInfo)o GetStream(String, CultureInfo) e specificare le impostazioni cultura di cui devono essere recuperate le risorse. Per recuperare le risorse delle impostazioni cultura correnti, specificare il valore della proprietà CultureInfo.CurrentCulture come argomento culture . Se il gestore di risorse non può recuperare le risorse di culture, utilizza le regole standard di fallback delle risorse per recuperare le risorse appropriate.

Esempio

Nell'esempio seguente viene illustrato come il gestore di risorse recupera le risorse direttamente dai file .resources. L'esempio è costituito da tre file di risorse basati su testo per le impostazioni cultura inglesi (Stati Uniti), francesi (Francia) e russe (Russia). L'inglese (Stati Uniti) rappresenta le impostazioni cultura predefinite dell'esempio. Le sue risorse vengono archiviate nel seguente file denominato Strings.txt:

Greeting=Hello
Prompt=What is your name?

Le risorse per le impostazioni cultura francesi (Francia) vengono archiviate nel seguente file, denominato Strings.fr-FR.txt:

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

Le risorse per le impostazioni cultura russe (Russia) vengono archiviate nel seguente file, denominato Strings.ru-RU.txt:

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

Di seguito viene riportato il codice sorgente per l'esempio. L'esempio crea un'istanza degli oggetti CultureInfo per le impostazioni cultura inglesi (Stati Uniti), inglesi (Canada), francesi (Francia) e russe (Russia) e imposta ognuna come le impostazioni cultura correnti. Il metodo ResourceManager.GetString(String, CultureInfo) fornisce quindi il valore della proprietà CultureInfo.CurrentCulture come argomento culture per recuperare le risorse specifiche delle impostazioni cultura appropriate.

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{0}!", 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!

È possibile compilare la versione C# dell'esempio eseguendo il file batch riportato di seguito. Se si usa Visual Basic, sostituire csc con vbc e l'estensione .cs con .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

Vedi anche