Partager via


Utilisation des fichiers .resx par programmation

Parce que les fichiers de ressources XML (.resx) doivent se composer de XML bien défini, notamment d'un en-tête qui doit suivre un schéma spécifique suivi par les données dans les paires nom/valeur, vous pouvez constater que la création de ces fichiers manuellement est sujette aux erreurs. Une autre solution consiste à créer par programmation des fichiers .resx en utilisant des types et des membres dans la bibliothèque de classes .NET Framework. Vous pouvez également utiliser la bibliothèque de classes .NET Framework pour extraire les ressources stockées dans les fichiers .resx. Cette rubrique explique comment vous pouvez utiliser les types et membres dans l'espace de noms System.Resources pour travailler avec des fichiers .resx.

Remarque AttentionAttention

Il est également possible d'utiliser des fichiers .resx autrement que par programmation.Lorsque vous ajoutez un fichier de ressources à un projet Visual Studio, Visual Studio fournit une interface pour la création et la maintenance d'un fichier .resx, et convertit automatiquement le fichier .resx en un fichier .resources au moment de la compilation.Vous pouvez également utiliser un éditeur de texte pour manipuler un fichier .resx directement.Cependant, pour éviter d'endommager le fichier, faites attention à ne pas modifier les informations binaires stockées dans le fichier.

Création d'un fichier .resx

Vous pouvez utiliser la classe System.Resources.ResXResourceWriter pour créer un fichier .resx par programmation, en procédant comme suit :

  1. Instanciez un objet ResXResourceWriter en appelant la méthode ResXResourceWriter.ResXResourceWriter(String) et en fournissant le nom du fichier .resx. Le nom du fichier doit inclure l'extension .resx. Si vous instanciez l'objet ResXResourceWriter dans un bloc using, vous n'avez pas à appeler explicitement la méthode ResXResourceWriter.Close dans l'étape 3.

  2. Appelez la méthode ResXResourceWriter.AddResource pour chaque ressource que vous souhaitez ajouter au fichier. Utilisez les surcharges de cette méthode pour ajouter des données de chaîne, d'objet et binaires (tableau d'octets). Si la ressource est un objet, il doit être sérialisable.

  3. Appelez la méthode ResXResourceWriter.Close pour générer le fichier de ressources et libérer toutes les ressources. Si l'objet ResXResourceWriter a été créé dans un bloc using, les ressources sont écrites dans le fichier .resx et les ressources utilisées par l'objet ResXResourceWriter sont libérées à la fin du bloc using.

Le fichier .resx résultant a l'en-tête approprié et une balise data pour chaque ressource ajoutée par la méthode ResXResourceWriter.AddResource.

Remarque AttentionAttention

N'utilisez pas de fichiers de ressources pour stocker des mots de passe, des informations sensibles ou des données privées.

L'exemple suivant crée par programmation un fichier .resx nommé CarResources.resx qui stocke six chaînes, une icône et deux objets définis par l'application (deux objets Automobile). Notez que la classe Automobile, définie et instanciée dans l'exemple, est marquée avec l'attribut SerializableAttribute.

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
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);  
      }
   }
}
Remarque importanteImportant

Vous pouvez également utiliser Visual Studio pour créer des fichiers .resx.Au moment de la compilation, Visual Studio utilise l'Outil Resource File Generator Tool (Resgen.exe) pour convertir le fichier .resx en un fichier de ressources binaire (.resources) et l'incorpore dans un assembly d'application ou un assembly satellite.

Vous ne pouvez pas incorporer un fichier .resx dans un exécutable runtime ou le compiler dans un assembly satellite. Vous devez convertir votre fichier .resx en fichier de ressources binaire (.resources) en utilisant l'Outil Resource File Generator Tool (Resgen.exe). Le fichier .resources résultant peut alors être incorporé dans un assembly d'application ou un assembly satellite. Pour plus d'informations, consultez Création de fichiers de ressources.

Énumération des ressources

Dans certains cas, vous pouvez avoir besoin d'extraire toutes les ressources, au lieu d'une ressource spécifique, d'un fichier .resx. Pour ce faire, vous pouvez utiliser la classe System.Resources.ResXResourceReader, qui fournit un énumérateur pour toutes les ressources dans le fichier .resx. La classe System.Resources.ResXResourceReader implémente IDictionaryEnumerator, qui retourne un objet DictionaryEntry qui représente une ressource particulière pour chaque itération de la boucle. Sa propriété DictionaryEntry.Key retourne la clé de la ressource et sa propriété DictionaryEntry.Value retourne la valeur de la ressource.

L'exemple suivant crée un objet ResXResourceReader pour le fichier CarResources.resx créé dans l'exemple précédent et itère au sein du fichier de ressources. Il ajoute les deux objets Automobile définis dans le fichier de ressources à un objet System.Collections.Generic.List<T> et cinq des six chaînes à un objet SortedList. Les valeurs de l'objet SortedList sont converties en un tableau de paramètres, utilisé pour afficher les en-têtes de colonnes dans la console. Les valeurs de propriété Automobile sont également affichées dans la console.

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
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

Extraction d'une ressource spécifique

En plus d'énumérer les éléments dans un fichier .resx, vous pouvez extraire une ressource spécifique par nom à l'aide de la classe System.Resources.ResXResourceSet. La méthode ResourceSet.GetString(String) extrait la valeur d'une ressource de type chaîne nommée. La méthode ResourceSet.GetObject(String) extrait la valeur d'un objet nommé ou de données binaires. La méthode retourne un objet qui doit être transtypé (en C#) ensuite ou converti (en Visual Basic) en un objet du type approprié.

L'exemple suivant extrait la chaîne de légende et l'icône d'un formulaire en fonction de leurs noms de ressource. Il extrait également les objets Automobile définis par l'application utilisés dans l'exemple précédent et les affiche dans un contrôle DataGridView.

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
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;
      }
   }
}

Conversion de fichiers .resx en fichiers .resources binaires

La conversion de fichiers .resx en fichiers de ressources binaires incorporés (.resources) a des avantages importants. Bien que les fichiers .resx soient faciles à lire et à gérer pendant le développement d'applications, ils sont rarement inclus avec les applications finies. S'ils sont distribués avec une application, ils existent en tant que fichiers séparés de l'exécutable d'application et ses bibliothèques d'accompagnement. Par opposition, les fichiers .resources sont incorporés dans l'exécutable d'application ou ses assemblys d'accompagnement. De plus, pour les applications localisées, compter sur les fichiers .resx fait peser la responsabilité du traitement du secours pour les ressources sur le développeur. Par opposition, si un ensemble d'assemblys satellites qui contiennent des fichiers .resources incorporés a été créé, le common language runtime gère le processus du secours de la ressource.

Pour convertir un fichier .resx en un fichier .resources, vous utilisez l'Outil Resource File Generator Tool (Resgen.exe), qui a la syntaxe de base suivante :

Resgen.exe .resxFilename

Le résultat est un fichier de ressources binaire qui a le même nom de fichier de base que le fichier .resx et une extension de fichier .resources. Ce fichier peut ensuite être compilé dans un exécutable ou une bibliothèque au moment de la compilation. Si vous utilisez le compilateur Visual Basic, utilisez la syntaxe suivante pour incorporer un fichier .resources dans l'exécutable d'une application :

vbc nom de fichier**.vb /resource:**.resxFilename

Si vous utilisez C#, la syntaxe est la suivante :

csc nom de fichier**.cs /resource:**.resxFilename

Le fichier .resources peut également être incorporé dans un assembly satellite à l'aide d'Assembly Linker (AL.exe), qui a la syntaxe de base suivante :

al resxFilename **/out:**assemblyFilename

Voir aussi

Référence

Resgen.exe (Resource File Generator)

Al.exe (Assembly Linker)

Concepts

Création de fichiers de ressources

Historique des modifications

Date

Historique

Motif

Décembre 2010

Ajout d'une rubrique.

Améliorations apportées aux informations.