System.Resources.ResourceReader クラス

この記事は、この API のリファレンス ドキュメントの補足説明です。

重要

このクラスのメソッドを信頼されていないデータを指定して呼び出すことには、セキュリティ上のリスクが伴います。 このクラスのメソッドの呼び出しは、信頼されたデータだけを指定して実行してください。 詳細については、「すべての入力の検証」を参照してください

このクラスは ResourceReader 、インターフェイスの標準実装を IResourceReader 提供します。 インスタンスは ResourceReader 、スタンドアロンの .resources ファイルまたはアセンブリに埋め込まれている .resources ファイルを表します。 これは、.resources ファイル内のリソースを列挙し、その名前と値のペアを取得するために使用されます。 これは、アセンブリに ResourceManager 埋め込まれている .resources ファイルから指定された名前付きリソースを取得するために使用されるクラスとは異なります。 この ResourceManager クラスは、名前が事前にわかっているリソースを取得するために使用されますが ResourceReader 、クラスはコンパイル時に番号または正確な名前が不明なリソースを取得する場合に便利です。 たとえば、アプリケーションはリソース ファイルを使用して、セクションとセクション内の項目に編成された構成情報を格納できます。セクション内のセクションまたは項目の数が事前にわかっていません。 その後、リソースに一般的な名前を付け (Section1、、、Section1Item2など)、オブジェクトをResourceReader使用Section1Item1して取得できます。

重要

この型は IDisposable インターフェイスを実装します。 型の使用が完了したら、直接的または間接的に型を破棄する必要があります。 直接的に型を破棄するには、try/catch ブロック内で Dispose メソッドを呼び出します。 間接的に型を破棄するには、using (C# の場合) または Using (Visual Basic 言語) などの言語構成要素を使用します。 詳細については、インターフェイスドキュメントの「IDisposable を実装するオブジェクトの使用」セクションを IDisposable 参照してください。

ResourceReader オブジェクトをインスタンス化する

.resources ファイルは、Resgen.exe (リソース ファイル ジェネレーター) によってテキスト ファイルまたは XML .resx ファイルからコンパイルされたバイナリ ファイルです。 オブジェクトは ResourceReader 、スタンドアロンの .resources ファイルまたはアセンブリに埋め込まれている .resources ファイルを表すことができます。

スタンドアロンの .resources ファイルから読み取るオブジェクトをインスタンス化 ResourceReader するには、入力ストリームまたは .resources ファイル名を含む文字列でクラス コンストラクターを使用 ResourceReader します。 次の例は、両方の方法を示しています。 最初のオブジェクトは、 ResourceReader そのファイル名を使用して名前が付けられた Resources1.resources .resources ファイルを表すオブジェクトをインスタンス化します。 2 つ目は、 ResourceReader ファイルから作成されたストリームを使用して名前が付けられた Resources2.resources .resources ファイルを表すオブジェクトをインスタンス化します。

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

埋め込まれた .resources ファイルを表すオブジェクトを作成 ResourceReader するには、.resources ファイルが埋め込まれているアセンブリからオブジェクトをインスタンス化 Assembly します。 そのメソッドは Assembly.GetManifestResourceStream 、コンストラクターに Stream 渡すことができるオブジェクトを ResourceReader(Stream) 返します。 次の例では、 ResourceReader 埋め込み .resources ファイルを表すオブジェクトをインスタンス化します。

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)

ResourceReader オブジェクトのリソースを列挙する

.resources ファイル内のリソースを列挙するには、オブジェクトを返すメソッドをGetEnumeratorSystem.Collections.IDictionaryEnumerator呼び出します。 メソッドを IDictionaryEnumerator.MoveNext 呼び出して、あるリソースから次のリソースに移動します。 このメソッドは、 false .resources ファイル内のすべてのリソースが列挙されたときに返されます。

Note

クラスはResourceReaderインターフェイスとメソッドをIEnumerableIEnumerable.GetEnumerator実装しますが、ResourceReader.GetEnumeratorメソッドは実装をIEnumerable.GetEnumerator提供しません。 代わりに、このメソッドは ResourceReader.GetEnumerator 、各リソースの IDictionaryEnumerator 名前と値のペアへのアクセスを提供するインターフェイス オブジェクトを返します。

コレクション内の個々のリソースは、次の 2 つの方法で取得できます。

  • コレクション内の各リソースを反復処理し、プロパティを System.Collections.IDictionaryEnumerator 使用 System.Collections.IDictionaryEnumerator してリソースの名前と値を取得できます。 すべてのリソースが同じ種類の場合、または各リソースのデータ型がわかっている場合は、この手法をお勧めします。

  • コレクションを反復処理し、メソッドを呼び出GetResourceDataしてリソースのデータをSystem.Collections.IDictionaryEnumerator取得するときに、各リソースの名前を取得できます。 各リソースのデータ型がわからない場合、または前の方法で例外がスローされる場合は、この方法をお勧めします。

IDictionaryEnumerator プロパティを使用してリソースを取得する

.resources ファイル内のリソースを列挙する最初の方法は、各リソースの名前と値のペアを直接取得することです。 メソッドを IDictionaryEnumerator.MoveNext 呼び出してコレクション内の各リソースに移動した後、プロパティからリソース名を IDictionaryEnumerator.Key 取得し、プロパティからリソース データを IDictionaryEnumerator.Value 取得できます。

次の例は、.resources ファイル内の各リソースの名前と値を取得する方法とIDictionaryEnumerator.Valueプロパティを使用して取得する方法をIDictionaryEnumerator.Key示しています。 この例を実行するには、文字列リソースを定義するために、ApplicationResources.txtという名前の次のテキスト ファイルを作成します。

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

次のコマンドを使用して、テキスト リソース ファイルを ApplicationResources.resources という名前のバイナリ ファイルに変換できます。

resgen ApplicationResources.txt

次の例では、クラスを ResourceReader 使用して、スタンドアロン バイナリ .resources ファイル内の各リソースを列挙し、そのキー名と対応する値を表示します。

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)

プロパティから IDictionaryEnumerator.Value リソース データを取得しようとすると、次の例外がスローされる可能性があります。

通常、これらの例外は、.resources ファイルが手動で変更された場合、型が定義されているアセンブリがアプリケーションに含まれていないか、誤って削除された場合、またはアセンブリが型より前の古いバージョンである場合にスローされます。 これらの例外のいずれかがスローされた場合は、次のセクションに示すように、各リソースを列挙し、メソッドを GetResourceData 呼び出すことによってリソースを取得できます。 この方法では、プロパティが返そうとしたデータ型に関するいくつかの情報が IDictionaryEnumerator.Value 提供されます。

GetResourceData を使用して名前でリソースを取得する

.resources ファイル内のリソースを列挙する 2 番目の方法では、メソッドを呼び出してファイル内のリソース間を IDictionaryEnumerator.MoveNext 移動することも含まれます。 リソースごとに、プロパティからリソースの名前を IDictionaryEnumerator.Key 取得し、その後、メソッドに GetResourceData(String, String, Byte[]) 渡してリソースのデータを取得します。 これは引数の resourceData バイト配列として返されます。

この方法は、リソース値を形成する実際のバイトを返すので、リソース名とプロパティから IDictionaryEnumerator.Key リソースの名前と IDictionaryEnumerator.Value 値を取得するよりも厄介です。 ただし、リソースを取得しようとすると例外がスローされた場合、メソッドはリソース GetResourceData のデータ型に関する情報を提供することで、例外のソースを識別するのに役立ちます。 リソースのデータ型を示す文字列の詳細については、次を参照してください GetResourceData

次の例は、この方法を使用してリソースを取得し、スローされた例外を処理する方法を示しています。 プログラムによって、4 つの文字列、1 つのブール値、1 つの整数、および 1 つのビットマップを含むバイナリ .resources ファイルが作成されます。 この例を実行するには、次の操作を行います。

  1. 次のソース コードをコンパイルして実行し、ContactResources.resources という名前の .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();
            }
        }
    }
    

    ソース コード ファイルの名前は CreateResources.cs です。 次のコマンドを使用して、C# でコンパイルできます。

    csc CreateResources.cs /r:library.dll
    
  2. 次のコードをコンパイルして実行し、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();
        }
    }
    

    ソース コードを変更した後 (たとえば、ブロックのtry最後に意図的に a FormatException をスローするなど)、この例を実行して、呼び出しを使用してGetResourceDataリソース情報を取得または再作成する方法を確認できます。