Uso dei file RESX a livello di codiceWorking with .resx Files Programmatically

Poiché i file di risorse XML (con estensione resx) devono essere costituiti da codice XML ben definito, comprensivo di un'intestazione che deve seguire uno schema specifico, seguita da dati in coppie nome/valore, la creazione manuale di questi file è soggetta a errori.Because XML resource (.resx) files must consist of well-defined XML, including a header that must follow a specific schema followed by data in name/value pairs, you may find that creating these files manually is error-prone. In alternativa, è possibile creare file con estensione resx a livello di codice usando tipi e membri inclusi nella libreria di classi .NET Framework.As an alternative, you can create .resx files programmatically by using types and members in the .NET Framework Class Library. La libreria di classi .NET Framework può essere usata anche per recuperare risorse archiviate in file con estensione resx.You can also use the .NET Framework Class Library to retrieve resources that are stored in .resx files. Questo argomento illustra come usare i tipi e i membri nello spazio dei nomi System.Resources per i file RESX.This topic explains how you can use the types and members in the System.Resources namespace to work with .resx files.

Tenere presente che questo articolo descrive solo l'uso di file XML (con estensione resx) che contengono risorse.Note that this article discusses working with XML (.resx) files that contain resources. Per informazioni sull'uso dei file di risorse binari che sono stati incorporati negli assembly, vedere l'argomento ResourceManager .For information on working with binary resource files that have been embedded in assemblies, see the ResourceManager topic.

Avviso

Esistono anche modi per usare i file RESX, oltre all'uso a livello di codice.There are also ways to work with .resx files other than programmatically. Quando si aggiunge un file di risorse a un progetto di Visual Studio, Visual Studio fornisce un'interfaccia per la creazione e la gestione di un file RESX e converte automaticamente il file RESX in un file con estensione resources in fase di compilazione.When you add a resource file to a Visual Studio project, Visual Studio provides an interface for creating and maintaining a .resx file, and automatically converts the .resx file to a .resources file at compile time. È anche possibile usare un editor di testo per modificare direttamente un file RESX.You can also use a text editor to manipulate a .resx file directly. Prestare comunque attenzione a non modificare le eventuali informazioni binarie archiviate nel file, per evitare di danneggiarlo.However, to avoid corrupting the file, be careful not to modify any binary information that is stored in the file.

Creazione di un file RESXCreating a .resx File

È possibile usare la classe System.Resources.ResXResourceWriter per creare un file RESX a livello di codice seguendo questa procedura:You can use the System.Resources.ResXResourceWriter class to create a .resx file programmatically, by following these steps:

  1. Creare un'istanza di un oggetto ResXResourceWriter chiamando il metodo ResXResourceWriter.ResXResourceWriter(String) e specificando il nome del file RESX.Instantiate a ResXResourceWriter object by calling the ResXResourceWriter.ResXResourceWriter(String) method and supplying the name of the .resx file. Il nome del file deve includere l'estensione resx.The file name must include the .resx extension. Se si crea un'istanza dell'oggetto ResXResourceWriter in un blocco using , non è necessario chiamare esplicitamente il metodo ResXResourceWriter.Close nel passaggio 3.If you instantiate the ResXResourceWriter object in a using block, you do not explicitly have to call the ResXResourceWriter.Close method in step 3.

  2. Chiamare il metodo ResXResourceWriter.AddResource per ogni risorsa da aggiungere al file.Call the ResXResourceWriter.AddResource method for each resource you want to add to the file. Usare l'overload di questo metodo per aggiungere dati stringa, oggetto e binari (matrice di byte).Use the overloads of this method to add string, object, and binary (byte array) data. Se la risorsa è un oggetto, deve essere serializzabile.If the resource is an object, it must be serializable.

  3. Chiamare il metodo ResXResourceWriter.Close per generare il file di risorse e per rilasciare tutte le risorse.Call the ResXResourceWriter.Close method to generate the resource file and to release all resources. Se l'oggetto ResXResourceWriter è stato creato all'interno di un blocco using , le risorse vengono scritte nel file RESX e le risorse usate dall'oggetto ResXResourceWriter vengono rilasciate alla fine del blocco using .If the ResXResourceWriter object was created within a using block, resources are written to the .resx file and the resources used by the ResXResourceWriter object are released at the end of the using block.

Il file RESX risultante ha l'intestazione appropriata e un tag data per ogni risorsa aggiunta dal metodo ResXResourceWriter.AddResource .The resulting .resx file has the appropriate header and a data tag for each resource added by the ResXResourceWriter.AddResource method.

Avviso

Non usare file di risorse per archiviare password, informazioni sensibili per la sicurezza o dati personali.Do not use resource files to store passwords, security-sensitive information, or private data.

Nell'esempio seguente viene creato un file con estensione resx denominato CarResources.resx che archivia sei stringhe, un'icona e due oggetti definiti dall'applicazione, ovvero due oggetti Automobile .The following example creates a .resx file named CarResources.resx that stores six strings, an icon, and two application-defined objects (two Automobile objects). Si noti che la classe Automobile , che viene definita e di cui viene creata un'istanza nell'esempio, è contrassegnata con l'attributo SerializableAttribute .Note that the Automobile class, which is defined and instantiated in the example, is tagged with the SerializableAttribute attribute.

using System;
using System.Drawing;
using System.Resources;

[Serializable()] public class Automobile
{
   private string carMake;
   private string carModel;
   private int carYear;
   private int carDoors;
   private int carCylinders;
   
   public Automobile(string make, string model, int year) :  
                     this(make, model, year, 0, 0)   
   { }
   
   public Automobile(string make, string model, int year, 
                     int doors, int cylinders)
   {                     
      this.carMake = make;
      this.carModel = model;
      this.carYear = year;
      this.carDoors = doors;
      this.carCylinders = cylinders;
   }

   public string Make {
      get { return this.carMake; }
   }       
   
   public string Model {
      get {return this.carModel; }
   }       
   
   public int Year {
      get { return this.carYear; }
   }       
   
   public int Doors {
      get { return this.carDoors; }
   }       
   
   public int Cylinders {
      get { return this.carCylinders; }
   }       
}

public class Example
{
   public static void Main()
   {
      // Instantiate an Automobile object.
      Automobile car1 = new Automobile("Ford", "Model N", 1906, 0, 4);
      Automobile car2 = new Automobile("Ford", "Model T", 1909, 2, 4);
      // Define a resource file named CarResources.resx.
      using (ResXResourceWriter resx = new ResXResourceWriter(@".\CarResources.resx"))
      {
         resx.AddResource("Title", "Classic American Cars");
         resx.AddResource("HeaderString1", "Make");
         resx.AddResource("HeaderString2", "Model");
         resx.AddResource("HeaderString3", "Year");
         resx.AddResource("HeaderString4", "Doors");
         resx.AddResource("HeaderString5", "Cylinders");
         resx.AddResource("Information", SystemIcons.Information); 
         resx.AddResource("EarlyAuto1", car1);  
         resx.AddResource("EarlyAuto2", car2);  
      }
   }
}
Imports System.Drawing
Imports System.Resources

<Serializable()> Public Class Automobile
   Private carMake As String
   Private carModel As String
   Private carYear As Integer
   Private carDoors AS Integer
   Private carCylinders As Integer
   
   Public Sub New(make As String, model As String, year As Integer) 
      Me.New(make, model, year, 0, 0)   
   End Sub
   
   Public Sub New(make As String, model As String, year As Integer, 
                  doors As Integer, cylinders As Integer)
      Me.carMake = make
      Me.carModel = model
      Me.carYear = year
      Me.carDoors = doors
      Me.carCylinders = cylinders
   End Sub

   Public ReadOnly Property Make As String
      Get
         Return Me.carMake
      End Get   
   End Property       
   
   Public ReadOnly Property Model As String
      Get
         Return Me.carModel
      End Get   
   End Property       
   
   Public ReadOnly Property Year As Integer
      Get
         Return Me.carYear
      End Get   
   End Property       
   
   Public ReadOnly Property Doors As Integer
      Get
         Return Me.carDoors
      End Get   
   End Property       
   
   Public ReadOnly Property Cylinders As Integer
      Get
         Return Me.carCylinders
      End Get   
   End Property       
End Class

Module Example
   Public Sub Main()
      ' Instantiate an Automobile object.
      Dim car1 As New Automobile("Ford", "Model N", 1906, 0, 4)
      Dim car2 As New Automobile("Ford", "Model T", 1909, 2, 4)
      ' Define a resource file named CarResources.resx.
      Using resx As New ResXResourceWriter(".\CarResources.resx")
         resx.AddResource("Title", "Classic American Cars")
         resx.AddResource("HeaderString1", "Make")
         resx.AddResource("HeaderString2", "Model")
         resx.AddResource("HeaderString3", "Year")
         resx.AddResource("HeaderString4", "Doors")
         resx.AddResource("HeaderString5", "Cylinders")
         resx.AddResource("Information", SystemIcons.Information) 
         resx.AddResource("EarlyAuto1", car1)
         resx.AddResource("EarlyAuto2", car2)  
      End Using
   End Sub
End Module

Importante

Si può anche usare Visual Studio per creare file RESX.You can also use Visual Studio to create .resx files. In fase di compilazione Visual Studio usa il generatore di file di risorse (Resgen.exe) per convertire il file RESX in una risorsa binaria (con estensione resources) e lo incorpora anche nell'assembly dell'applicazione o in un assembly satellite.At compile time, Visual Studio uses the Resource File Generator (Resgen.exe) to convert the .resx file to a binary resource (.resources) file, and also embeds it in either an application assembly or a satellite assembly.

Non è possibile incorporare un file RESX in un eseguibile di runtime o compilarlo in un assembly satellite.You cannot embed a .resx file in a runtime executable or compile it into a satellite assembly. Il file RESX deve essere convertito in un file di risorse binario (con estensione resources) usando il generatore di file di risorse (Resgen.exe).You must convert your .resx file into a binary resource (.resources) file by using the Resource File Generator (Resgen.exe). Successivamente, il file con estensione resources risultante può essere incorporato in un assembly dell'applicazione o in un assembly satellite.The resulting .resources file can then be embedded in an application assembly or a satellite assembly. Per altre informazioni, vedere Creating Resource Files.For more information, see Creating Resource Files.

Enumerazione delle risorseEnumerating Resources

In alcuni casi può essere necessario recuperare tutte le risorse anziché una risorsa specifica da un file RESX.In some cases, you may want to retrieve all resources, instead of a specific resource, from a .resx file. A questo scopo, si può usare la classe System.Resources.ResXResourceReader , che fornisce un enumeratore per tutte le risorse nel file RESX.To do this, you can use the System.Resources.ResXResourceReader class, which provides an enumerator for all resources in the .resx file. La classe System.Resources.ResXResourceReader implementa IDictionaryEnumerator, che restituisce un oggetto DictionaryEntry che rappresenta una risorsa specifica per ogni iterazione del ciclo.The System.Resources.ResXResourceReader class implements IDictionaryEnumerator, which returns a DictionaryEntry object that represents a particular resource for each iteration of the loop. La relativa proprietà DictionaryEntry.Key restituisce la chiave della risorsa e la proprietà DictionaryEntry.Value restituisce il valore della risorsa.Its DictionaryEntry.Key property returns the resource's key, and its DictionaryEntry.Value property returns the resource's value.

L'esempio seguente consente di creare un oggetto ResXResourceReader per il file CarResources.resx creato nell'esempio precedente e di scorrere il file di risorse.The following example creates a ResXResourceReader object for the CarResources.resx file created in the previous example and iterates through the resource file. Aggiunge i due oggetti Automobile definiti nel file di risorse a un oggetto System.Collections.Generic.List<T> e aggiunge cinque delle sei stringhe a un oggetto SortedList .It adds the two Automobile objects that are defined in the resource file to a System.Collections.Generic.List<T> object, and it adds five of the six strings to a SortedList object. I valori nell'oggetto SortedList vengono convertiti in una matrice di parametri, usata per visualizzare le intestazioni di colonna nella console.The values in the SortedList object are converted to a parameter array, which is used to display column headings to the console. Nella console vengono visualizzati anche i valori della proprietà Automobile .The Automobile property values are also displayed to the console.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Resources;

public class Example
{
   public static void Main()
   {
      string resxFile = @".\CarResources.resx";
      List<Automobile> autos = new List<Automobile>();
      SortedList headers = new SortedList();
      
      using (ResXResourceReader resxReader = new ResXResourceReader(resxFile))
      {
         foreach (DictionaryEntry entry in resxReader) {
            if (((string) entry.Key).StartsWith("EarlyAuto"))
               autos.Add((Automobile) entry.Value); 
            else if (((string) entry.Key).StartsWith("Header")) 
               headers.Add((string) entry.Key, (string) entry.Value);      
         } 
      }
      string[] headerColumns = new string[headers.Count];
      headers.GetValueList().CopyTo(headerColumns, 0);
      Console.WriteLine("{0,-8} {1,-10} {2,-4}   {3,-5}   {4,-9}\n", 
                        headerColumns);
      foreach (var auto in autos)                        
         Console.WriteLine("{0,-8} {1,-10} {2,4}   {3,5}   {4,9}", 
                           auto.Make, auto.Model, auto.Year, 
                           auto.Doors, auto.Cylinders);
   }
}
// The example displays the following output:
//       Make     Model      Year   Doors   Cylinders
//       
//       Ford     Model N    1906       0           4
//       Ford     Model T    1909       2           4
Imports System.Collections
Imports System.Collections.Generic
Imports System.Resources

Module Example
   Public Sub Main()
      Dim resxFile As String = ".\CarResources.resx"
      Dim autos As New List(Of Automobile)
      Dim headers As New SortedList()
      
      Using resxReader As New ResXResourceReader(resxFile)
         For Each entry As DictionaryEntry In resxReader
            If CType(entry.Key, String).StartsWith("EarlyAuto") Then
               autos.Add(CType(entry.Value, Automobile)) 
            Else If CType(entry.Key, String).StartsWith("Header") Then
               headers.Add(CType(entry.Key, String), CType(entry.Value, String))      
            End If 
         Next 
      End Using
      Dim headerColumns(headers.Count - 1) As String 
      headers.GetValueList().CopyTo(headerColumns, 0)
      Console.WriteLine("{0,-8} {1,-10} {2,-4}   {3,-5}   {4,-9}", 
                        headerColumns)
      Console.WriteLine()
      For Each auto In autos                        
         Console.WriteLine("{0,-8} {1,-10} {2,4}   {3,5}   {4,9}", 
                           auto.Make, auto.Model, auto.Year, 
                           auto.Doors, auto.Cylinders)
      Next
   End Sub
End Module
' The example displays the following output:
'       Make     Model      Year   Doors   Cylinders
'       
'       Ford     Model N    1906       0           4
'       Ford     Model T    1909       2           4

Recupero di una risorsa specificaRetrieving a Specific Resource

Oltre a enumerare gli elementi in un file RESX, è possibile recuperare una risorsa specifica in base al nome tramite la classe System.Resources.ResXResourceSet .In addition to enumerating the items in a .resx file, you can retrieve a specific resource by name by using the System.Resources.ResXResourceSet class. Il metodo ResourceSet.GetString(String) recupera il valore di una risorsa di tipo stringa denominata.The ResourceSet.GetString(String) method retrieves the value of a named string resource. Il metodo ResourceSet.GetObject(String) recupera il valore di un oggetto denominato o di dati binari.The ResourceSet.GetObject(String) method retrieves the value of a named object or binary data. Il metodo restituisce un oggetto di cui deve essere eseguito il cast (in C#) o da convertire (in Visual Basic) in un oggetto del tipo appropriato.The method returns an object that must then be cast (in C#) or converted (in Visual Basic) to an object of the appropriate type.

L'esempio seguente recupera l'icona e la stringa della didascalia di un form in base ai nomi delle risorse corrispondenti.The following example retrieves a form's caption string and icon by their resource names. Recupera anche gli oggetti Automobile definiti dall'applicazione usati nell'esempio precedente e li visualizza in un controllo DataGridView .It also retrieves the application-defined Automobile objects used in the previous example and displays them in a DataGridView control.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Resources;
using System.Windows.Forms;

public class CarDisplayApp : Form
{
   private const string resxFile = @".\CarResources.resx";
   Automobile[] cars;

   public static void Main()
   {
      CarDisplayApp app = new CarDisplayApp();
      Application.Run(app);
   }

   public CarDisplayApp()
   {
      // Instantiate controls.
      PictureBox pictureBox = new PictureBox();
      pictureBox.Location = new Point(10, 10);
      this.Controls.Add(pictureBox);
      DataGridView grid = new DataGridView();
      grid.Location = new Point(10, 60);
      this.Controls.Add(grid);
      
      // Get resources from .resx file.
      using (ResXResourceSet resxSet = new ResXResourceSet(resxFile))
      {
         // Retrieve the string resource for the title.
         this.Text = resxSet.GetString("Title");
         // Retrieve the image.
         Icon image = (Icon) resxSet.GetObject("Information", true);
         if (image != null)
            pictureBox.Image = image.ToBitmap();

         // Retrieve Automobile objects.  
         List<Automobile> carList = new List<Automobile>();
         string resName = "EarlyAuto";
         Automobile auto; 
         int ctr = 1;
         do {
            auto = (Automobile) resxSet.GetObject(resName + ctr.ToString());
            ctr++;
            if (auto != null) 
               carList.Add(auto);
         } while (auto != null);
         cars = carList.ToArray();
         grid.DataSource = cars;
      }
   }
}
Imports System.Collections.Generic
Imports System.Drawing
Imports System.Resources
Imports System.Windows.Forms

Public Class CarDisplayApp : Inherits Form 
   Private Const resxFile As String = ".\CarResources.resx"
   Dim cars() As Automobile
   
   Public Shared Sub Main()
      Dim app As New CarDisplayApp()
      Application.Run(app)
   End Sub
   
   Public Sub New()
      ' Instantiate controls.
      Dim pictureBox As New PictureBox()
      pictureBox.Location = New Point(10, 10)
      Me.Controls.Add(pictureBox)
      Dim grid As New DataGridView()
      grid.Location = New Point(10, 60)
      Me.Controls.Add(grid)
      
      ' Get resources from .resx file.
      Using resxSet As New ResXResourceSet(resxFile)
         ' Retrieve the string resource for the title.
         Me.Text = resxSet.GetString("Title")
         ' Retrieve the image.
         Dim image As Icon = CType(resxSet.GetObject("Information", True), Icon)
         If image IsNot Nothing Then
            pictureBox.Image = image.ToBitmap()
         End If

         ' Retrieve Automobile objects.  
         Dim carList As New List(Of Automobile)
         Dim resName As String = "EarlyAuto"
         Dim auto As Automobile 
         Dim ctr As Integer = 1
         Do
            auto = CType(resxSet.GetObject(resName + ctr.ToString()), Automobile)
            ctr += 1
            If auto IsNot Nothing Then carList.Add(auto)
         Loop While auto IsNot Nothing
         cars = carList.ToArray()
         grid.DataSource = cars
      End Using
   End Sub
End Class

Conversione dei file RESX in file binari con estensione resourcesConverting .resx Files to Binary .resources Files

La conversione dei file RESX in file di risorse binari incorporati (con estensione resources) presenta vantaggi significativi.Converting .resx files to embedded binary resource (.resources) files has significant advantages. Sebbene i file RESX siano facili da leggere e gestire durante lo sviluppo di applicazioni, è raro che siano inclusi nelle applicazioni finite.Although .resx files are easy to read and maintain during application development, they are rarely included with finished applications. Se vengono distribuiti con un'applicazione, sono costituiti da file separati indipendenti dall'eseguibile dell'applicazione e dalle librerie associate.If they are distributed with an application, they exist as separate files apart from the application executable and its accompanying libraries. Al contrario, i file con estensione resources sono incorporati nell'eseguibile dell'applicazione o negli assembly associati.In contrast, .resources files are embedded in the application executable or its accompanying assemblies. Inoltre, per le applicazioni localizzate, se si basano su file RESX in fase di esecuzione la responsabilità della gestione del fallback delle risorse ricade sullo sviluppatore.In addition, for localized applications, relying on .resx files at run time places the responsibility for handling resource fallback on the developer. Se invece è stato creato un set di assembly satellite che contengono i file con estensione resources incorporati, il processo di fallback delle risorse viene gestito da Common Language Runtime.In contrast, if a set of satellite assemblies that contain embedded .resources files has been created, the common language runtime handles the resource fallback process.

Per convertire un file con estensione resx in un file con estensione resources, usare il generatore di file di risorse (Resgen.exe), con la seguente sintassi di base:To convert a .resx file to a .resources file, you use the Resource File Generator (Resgen.exe), which has the following basic syntax:

Resgen.exe .resxNomeFileResgen.exe .resxFilename

Il risultato è un file di risorse binario con lo stesso nome file radice del file RESX e l'estensione resources.The result is a binary resource file that has the same root file name as the .resx file and a .resources file extension. Questo file può quindi essere compilato in un file eseguibile o una libreria in fase di compilazione.This file can then be compiled into an executable or a library at compile time. Se si usa il compilatore Visual Basic, usare la sintassi seguente per incorporare un file con estensione resources nell'eseguibile di un'applicazione:If you are using the Visual Basic compiler, use the following syntax to embed a .resources file in an application's executable:

vbc filename .vb /resource: .resourcesFilenamevbc filename .vb -resource: .resourcesFilename

Se si usa C#, la sintassi è la seguente:If you are using C#, the syntax is as follows:

csc filename .cs -resource: .resourcesFilenamecsc filename .cs -resource: .resourcesFilename

Il file con estensione resources può essere incorporato in un assembly satellite anche tramite Assembly Linker (AL.exe), che ha la seguente sintassi di base:The .resources file can also be embedded in a satellite assembly by using Assembly Linker (AL.exe), which has the following basic syntax:

al resourcesFilename -out: assemblyFilenameal resourcesFilename -out: assemblyFilename

Vedere ancheSee Also

Creazione dei file di risorsaCreating Resource Files
Resgen.exe (generatore di file di risorse)Resgen.exe (Resource File Generator)
Al.exe (Assembly Linker)Al.exe (Assembly Linker)