Partager via


Classe System.Resources.ResourceReader

Cet article vous offre des remarques complémentaires à la documentation de référence pour cette API.

Important

L’appel de méthodes de cette classe avec des données non approuvées est un risque de sécurité. Appelez les méthodes de cette classe avec des données approuvées uniquement. Pour plus d’informations, consultez Valider toutes les entrées.

La ResourceReader classe fournit une implémentation standard de l’interface IResourceReader . Une ResourceReader instance représente un fichier .resources autonome ou un fichier .resources incorporé dans un assembly. Il est utilisé pour énumérer les ressources d’un fichier .resources et récupérer ses paires nom/valeur. Il diffère de la ResourceManager classe, utilisée pour récupérer les ressources nommées spécifiées à partir d’un fichier .resources incorporé dans un assembly. La ResourceManager classe est utilisée pour récupérer des ressources dont les noms sont connus à l’avance, tandis que la classe est utile pour récupérer des ressources dont le ResourceReader nombre ou les noms précis ne sont pas connus au moment de la compilation. Par exemple, une application peut utiliser un fichier de ressources pour stocker les informations de configuration organisées en sections et éléments d’une section, où le nombre de sections ou d’éléments d’une section n’est pas connu à l’avance. Les ressources peuvent ensuite être nommées génériquement (par Section1exemple, , Section1Item1Section1Item2, etc.) et récupérées à l’aide d’un ResourceReader objet.

Important

Ce type implémente l'interface IDisposable. Une fois que vous avez fini d’utiliser le type, vous devez le supprimer directement ou indirectement. Pour supprimer directement le type Dispose, appelez sa méthode dans un bloc try/catch. Pour la supprimer indirectement, utilisez une construction de langage telle que using (dans C#) ou Using (dans Visual Basic). Pour plus d’informations, consultez la section « Utilisation d’un objet implémentant IDisposable » dans la documentation de l’interface IDisposable .

Instancier un objet ResourceReader

Un fichier .resources est un fichier binaire qui a été compilé à partir d’un fichier texte ou d’un fichier .resx XML par Resgen.exe (Générateur de fichiers de ressources). Un ResourceReader objet peut représenter un fichier .resources autonome ou un fichier .resources incorporé dans un assembly.

Pour instancier un ResourceReader objet qui lit à partir d’un fichier .resources autonome, utilisez le ResourceReader constructeur de classe avec un flux d’entrée ou une chaîne qui contient le nom du fichier .resources. L’exemple suivant illustre les deux approches. Le premier instancie un ResourceReader objet qui représente un fichier .resources nommé Resources1.resources à l’aide de son nom de fichier. Le deuxième instancie un ResourceReader objet qui représente un fichier .resources nommé Resources2.resources à l’aide d’un flux créé à partir du fichier.

// Instantiate a standalone .resources file from its filename.
var rr1 = new System.Resources.ResourceReader("Resources1.resources");

// Instantiate a standalone .resources file from a stream.
var fs = new System.IO.FileStream(@".\Resources2.resources",
                                  System.IO.FileMode.Open);
var rr2 = new System.Resources.ResourceReader(fs);
' Instantiate a standalone .resources file from its filename.
Dim rr1 As New System.Resources.ResourceReader("Resources1.resources")

' Instantiate a standalone .resources file from a stream.
Dim fs As New System.IO.FileStream(".\Resources2.resources",
                                   System.IO.FileMode.Open)
Dim rr2 As New System.Resources.ResourceReader(fs)

Pour créer un ResourceReader objet qui représente un fichier .resources incorporé, instanciez un Assembly objet à partir de l’assembly dans lequel le fichier .resources est incorporé. Sa Assembly.GetManifestResourceStream méthode retourne un Stream objet qui peut être transmis au ResourceReader(Stream) constructeur. L’exemple suivant instancie un ResourceReader objet qui représente un fichier .resources incorporé.

System.Reflection.Assembly assem =
             System.Reflection.Assembly.LoadFrom(@".\MyLibrary.dll");
System.IO.Stream fs =
             assem.GetManifestResourceStream("MyCompany.LibraryResources.resources");
var rr = new System.Resources.ResourceReader(fs);
Dim assem As System.Reflection.Assembly = 
             System.Reflection.Assembly.LoadFrom(".\MyLibrary.dll") 
Dim fs As System.IO.Stream = 
             assem.GetManifestResourceStream("MyCompany.LibraryResources.resources")
Dim rr As New System.Resources.ResourceReader(fs)

Énumérer les ressources d’un objet ResourceReader

Pour énumérer les ressources d’un fichier .resources, vous appelez la GetEnumerator méthode, qui retourne un System.Collections.IDictionaryEnumerator objet. Vous appelez la IDictionaryEnumerator.MoveNext méthode pour passer d’une ressource à l’autre. La méthode retourne false lorsque toutes les ressources du fichier .resources ont été énumérées.

Remarque

Bien que la ResourceReader classe implémente l’interface IEnumerable et la IEnumerable.GetEnumerator méthode, la ResourceReader.GetEnumerator méthode ne fournit pas l’implémentation IEnumerable.GetEnumerator . Au lieu de cela, la ResourceReader.GetEnumerator méthode retourne un objet d’interface IDictionaryEnumerator qui fournit l’accès à la paire nom/valeur de chaque ressource.

Vous pouvez récupérer les ressources individuelles de la collection de deux manières :

  • Vous pouvez itérer chaque ressource dans la System.Collections.IDictionaryEnumerator collection et utiliser System.Collections.IDictionaryEnumerator des propriétés pour récupérer le nom et la valeur de la ressource. Nous vous recommandons cette technique lorsque toutes les ressources sont du même type, ou que vous connaissez le type de données de chaque ressource.

  • Vous pouvez récupérer le nom de chaque ressource lorsque vous itérerez la System.Collections.IDictionaryEnumerator collection et appelez la GetResourceData méthode pour récupérer les données de la ressource. Nous vous recommandons cette approche lorsque vous ne connaissez pas le type de données de chaque ressource ou si l’approche précédente lève des exceptions.

Récupérer des ressources à l’aide des propriétés IDictionaryEnumerator

La première méthode d’énumération des ressources dans un fichier .resources implique de récupérer directement la paire nom/valeur de chaque ressource. Après avoir appelé la IDictionaryEnumerator.MoveNext méthode pour passer à chaque ressource de la collection, vous pouvez récupérer le nom de la ressource à partir de la IDictionaryEnumerator.Key propriété et les données de ressource de la IDictionaryEnumerator.Value propriété.

L’exemple suivant montre comment récupérer le nom et la valeur de chaque ressource dans un fichier .resources à l’aide des propriétés et IDictionaryEnumerator.Value des IDictionaryEnumerator.Key propriétés. Pour exécuter l’exemple, créez le fichier texte suivant nommé ApplicationResources.txt pour définir des ressources de chaîne.

Title="Contact Information"
Label1="First Name:"
Label2="Middle Name:"
Label3="Last Name:"
Label4="SSN:"
Label5="Street Address:"
Label6="City:"
Label7="State:"
Label8="Zip Code:"
Label9="Home Phone:"
Label10="Business Phone:"
Label11="Mobile Phone:"
Label12="Other Phone:"
Label13="Fax:"
Label14="Email Address:"
Label15="Alternate Email Address:"

Vous pouvez ensuite convertir le fichier de ressources texte en fichier binaire nommé ApplicationResources.resources à l’aide de la commande suivante :

resgen ApplicationResources.txt

L’exemple suivant utilise ensuite la ResourceReader classe pour énumérer chaque ressource dans le fichier .resources binaire autonome et afficher son nom de clé et sa valeur correspondante.

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

public class Example1
{
   public static void Run()
   {
      Console.WriteLine("Resources in ApplicationResources.resources:");
      ResourceReader res = new ResourceReader(@".\ApplicationResources.resources");
      IDictionaryEnumerator dict = res.GetEnumerator();
      while (dict.MoveNext())
         Console.WriteLine("   {0}: '{1}' (Type {2})", 
                           dict.Key, dict.Value, dict.Value.GetType().Name);
      res.Close();
   }
}
// The example displays the following output:
//       Resources in ApplicationResources.resources:
//          Label3: '"Last Name:"' (Type String)
//          Label2: '"Middle Name:"' (Type String)
//          Label1: '"First Name:"' (Type String)
//          Label7: '"State:"' (Type String)
//          Label6: '"City:"' (Type String)
//          Label5: '"Street Address:"' (Type String)
//          Label4: '"SSN:"' (Type String)
//          Label9: '"Home Phone:"' (Type String)
//          Label8: '"Zip Code:"' (Type String)
//          Title: '"Contact Information"' (Type String)
//          Label12: '"Other Phone:"' (Type String)
//          Label13: '"Fax:"' (Type String)
//          Label10: '"Business Phone:"' (Type String)
//          Label11: '"Mobile Phone:"' (Type String)
//          Label14: '"Email Address:"' (Type String)
//          Label15: '"Alternate Email Address:"' (Type String)
Imports System.Collections
Imports System.Resources

Module Example2
    Public Sub Main()
        Console.WriteLine("Resources in ApplicationResources.resources:")
        Dim res As New ResourceReader(".\ApplicationResources.resources")
        Dim dict As IDictionaryEnumerator = res.GetEnumerator()
        Do While dict.MoveNext()
            Console.WriteLine("   {0}: '{1}' (Type {2})", dict.Key, dict.Value, dict.Value.GetType().Name)
        Loop
        res.Close()
    End Sub
End Module
' The example displays output like the following:
'       Resources in ApplicationResources.resources:
'          Label3: '"Last Name:"' (Type String)
'          Label2: '"Middle Name:"' (Type String)
'          Label1: '"First Name:"' (Type String)
'          Label7: '"State:"' (Type String)
'          Label6: '"City:"' (Type String)
'          Label5: '"Street Address:"' (Type String)
'          Label4: '"SSN:"' (Type String)
'          Label9: '"Home Phone:"' (Type String)
'          Label8: '"Zip Code:"' (Type String)
'          Title: '"Contact Information"' (Type String)
'          Label12: '"Other Phone:"' (Type String)
'          Label13: '"Fax:"' (Type String)
'          Label10: '"Business Phone:"' (Type String)
'          Label11: '"Mobile Phone:"' (Type String)
'          Label14: '"Email Address:"' (Type String)
'          Label15: '"Alternate Email Address:"' (Type String)

La tentative de récupération des données de ressource à partir de la IDictionaryEnumerator.Value propriété peut lever les exceptions suivantes :

  • R FormatException si les données ne sont pas au format attendu.
  • R FileNotFoundException si l’assembly qui contient le type auquel les données appartiennent est introuvable.
  • R TypeLoadException si le type auquel les données appartiennent ne peut pas être trouvé.

En règle générale, ces exceptions sont levées si le fichier .resources a été modifié manuellement, si l’assembly dans lequel un type est défini n’a pas été inclus dans une application ou a été supprimé par inadvertance, ou si l’assembly est une version antérieure qui précède un type. Si l’une de ces exceptions est levée, vous pouvez récupérer des ressources en énumérant chaque ressource et en appelant la GetResourceData méthode, comme le montre la section suivante. Cette approche vous fournit des informations sur le type de données que la IDictionaryEnumerator.Value propriété a tenté de retourner.

Récupérer des ressources par nom avec GetResourceData

La deuxième approche pour énumérer des ressources dans un fichier .resources implique également de parcourir les ressources du fichier en appelant la IDictionaryEnumerator.MoveNext méthode. Pour chaque ressource, vous récupérez le nom de la ressource à partir de la IDictionaryEnumerator.Key propriété, qui est ensuite passée à la méthode pour récupérer les données de la GetResourceData(String, String, Byte[]) ressource. Cette propriété est retournée sous la forme d’un tableau d’octets dans l’argument resourceData .

Cette approche est plus maladroite que la récupération du nom et de la valeur de la ressource à partir des IDictionaryEnumerator.Key propriétés et IDictionaryEnumerator.Value des propriétés, car elle retourne les octets réels qui forment la valeur de la ressource. Toutefois, si la tentative de récupération de la ressource lève une exception, la GetResourceData méthode peut aider à identifier la source de l’exception en fournissant des informations sur le type de données de la ressource. Pour plus d’informations sur la chaîne qui indique le type de données de la ressource, consultez GetResourceData.

L’exemple suivant montre comment utiliser cette approche pour récupérer des ressources et gérer les exceptions levées. Il crée par programme un fichier .resources binaire qui contient quatre chaînes, un booléen, un entier et une bitmap. Pour exécuter l’exemple, procédez comme suit :

  1. Compilez et exécutez le code source suivant, qui crée un fichier .resources nommé ContactResources.resources.

    using System.Drawing;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Resources;
    using System.Runtime.Versioning;
    
    public class Example5
    {
        [SupportedOSPlatform("windows")]
        public static void Run()
        {
            // Bitmap as stream.
            MemoryStream bitmapStream = new MemoryStream();
            Bitmap bmp = new Bitmap(@".\ContactsIcon.jpg");
            bmp.Save(bitmapStream, ImageFormat.Jpeg);
    
            // Define resources to be written.
            using (ResourceWriter rw = new ResourceWriter(@".\ContactResources.resources"))
            {
                rw.AddResource("Title", "Contact List");
                rw.AddResource("NColumns", 5);
                rw.AddResource("Icon", bitmapStream);
                rw.AddResource("Header1", "Name");
                rw.AddResource("Header2", "City");
                rw.AddResource("Header3", "State");
                rw.AddResource("ClientVersion", true);
                rw.Generate();
            }
        }
    }
    

    Le fichier de code source est nommé CreateResources.cs. Vous pouvez le compiler en C# à l’aide de la commande suivante :

    csc CreateResources.cs /r:library.dll
    
  2. Compilez et exécutez le code suivant pour énumérer les ressources dans le fichier ContactResources.resources.

    using System;
    using System.Collections;
    using System.Drawing;
    using System.IO;
    using System.Resources;
    using System.Runtime.Versioning;
    
    public class Example6
    {
        [SupportedOSPlatform("windows")]
        public static void Run()
        {
            ResourceReader rdr = new ResourceReader(@".\ContactResources.resources");
            IDictionaryEnumerator dict = rdr.GetEnumerator();
            while (dict.MoveNext())
            {
                Console.WriteLine("Resource Name: {0}", dict.Key);
                try
                {
                    Console.WriteLine("   Value: {0}", dict.Value);
                }
                catch (FileNotFoundException)
                {
                    Console.WriteLine("   Exception: A file cannot be found.");
                    DisplayResourceInfo(rdr, (string)dict.Key, false);
                }
                catch (FormatException)
                {
                    Console.WriteLine("   Exception: Corrupted data.");
                    DisplayResourceInfo(rdr, (string)dict.Key, true);
                }
                catch (TypeLoadException)
                {
                    Console.WriteLine("   Exception: Cannot load the data type.");
                    DisplayResourceInfo(rdr, (string)dict.Key, false);
                }
            }
        }
    
        [SupportedOSPlatform("windows")]
        private static void DisplayResourceInfo(ResourceReader rr,
                                        string key, bool loaded)
        {
            string dataType = null;
            byte[] data = null;
            rr.GetResourceData(key, out dataType, out data);
    
            // Display the data type.
            Console.WriteLine("   Data Type: {0}", dataType);
            // Display the bytes that form the available data.      
            Console.Write("   Data: ");
            int lines = 0;
            foreach (var dataItem in data)
            {
                lines++;
                Console.Write("{0:X2} ", dataItem);
                if (lines % 25 == 0)
                    Console.Write("\n         ");
            }
            Console.WriteLine();
            // Try to recreate current state of data.
            // Do: Bitmap, DateTimeTZI
            switch (dataType)
            {
                // Handle internally serialized string data (ResourceTypeCode members).
                case "ResourceTypeCode.String":
                    BinaryReader reader = new BinaryReader(new MemoryStream(data));
                    string binData = reader.ReadString();
                    Console.WriteLine("   Recreated Value: {0}", binData);
                    break;
                case "ResourceTypeCode.Int32":
                    Console.WriteLine("   Recreated Value: {0}",
                                      BitConverter.ToInt32(data, 0));
                    break;
                case "ResourceTypeCode.Boolean":
                    Console.WriteLine("   Recreated Value: {0}",
                                      BitConverter.ToBoolean(data, 0));
                    break;
                // .jpeg image stored as a stream.
                case "ResourceTypeCode.Stream":
                    const int OFFSET = 4;
                    int size = BitConverter.ToInt32(data, 0);
                    Bitmap value1 = new Bitmap(new MemoryStream(data, OFFSET, size));
                    Console.WriteLine("   Recreated Value: {0}", value1);
                    break;
                default:
                    break;
            }
            Console.WriteLine();
        }
    }
    

    Après avoir modifié le code source (par exemple, en lèvent délibérément une FormatException à la fin du try bloc), vous pouvez exécuter l’exemple pour voir comment les appels GetResourceData vous permettent de récupérer ou de recréer certaines informations de ressource.