注
この記事は .NET Framework に適用されます。 .NET 5 以降 (.NET Core を含む) に適用される情報については、「 .resx ファイル内のリソース」を参照してください。
XML リソース (.resx) ファイルは、適切に定義された XML で構成されている必要があります。これには、特定のスキーマに従う必要があるヘッダーと、名前と値のペアのデータが含まれる必要があるため、これらのファイルを手動で作成するとエラーが発生しやすい場合があります。 別の方法として、.NET クラス ライブラリの型とメンバーを使用して、プログラムで .resx ファイルを作成することもできます。 .NET クラス ライブラリを使用して、.resx ファイルに格納されているリソースを取得することもできます。 この記事では、 System.Resources 名前空間の型とメンバーを使用して .resx ファイルを操作する方法について説明します。
この記事では、リソースを含む XML (.resx) ファイルの操作について説明します。 アセンブリに埋め込まれているバイナリ リソース ファイルの操作については、 ResourceManagerを参照してください。
Warnung
プログラム以外の .resx ファイルを操作する方法もあります。 Visual Studio プロジェクトにリソース ファイルを追加すると、Visual Studio は .resx ファイルを作成および保守するためのインターフェイスを提供し、コンパイル時に .resx ファイルを .resources ファイルに自動的に変換します。 テキスト エディターを使用して、.resx ファイルを直接操作することもできます。 ただし、ファイルの破損を回避するには、ファイルに格納されているバイナリ情報を変更しないように注意してください。
.resx ファイルを作成する
次の手順に従って、 System.Resources.ResXResourceWriter クラスを使用してプログラムで .resx ファイルを作成できます。
ResXResourceWriter メソッドを呼び出し、.resx ファイルの名前を指定して、ResXResourceWriter(String) オブジェクトをインスタンス化します。 ファイル名には、拡張子 .resx を含める必要があります。 ResXResourceWriter ブロック内の
using
オブジェクトをインスタンス化する場合、手順 3 でResXResourceWriter.Close メソッドを明示的に呼び出す必要はありません。ファイルに追加するリソースごとに ResXResourceWriter.AddResource メソッドを呼び出します。 このメソッドのオーバーロードを使用して、文字列、オブジェクト、バイナリ (バイト配列) データを追加します。 リソースがオブジェクトの場合は、シリアル化可能である必要があります。
ResXResourceWriter.Close メソッドを呼び出して、リソース ファイルを生成し、すべてのリソースを解放します。 ResXResourceWriter オブジェクトが
using
ブロック内に作成された場合、リソースは .resx ファイルに書き込まれ、ResXResourceWriter オブジェクトによって使用されるリソースは、using
ブロックの最後に解放されます。
結果の .resx ファイルには、data
メソッドによって追加された各リソースの適切なヘッダーとResXResourceWriter.AddResource タグがあります。
Warnung
パスワード、セキュリティの配慮が必要な情報、プライベートなデータなどの格納には、リソース ファイルを使用しないでください。
次の例では、6 つの文字列、アイコン、および 2 つのアプリケーション定義オブジェクト (2 つの Automobile
オブジェクト) を格納する CarResources.resx という名前の .resx ファイルを作成します。 この例で定義およびインスタンス化された Automobile
クラスには、 SerializableAttribute 属性が付けられます。
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
ヒント
Visual Studio を使用して .resx ファイルを作成することもできます。 コンパイル時に、Visual Studio は リソース ファイル ジェネレーター (Resgen.exe) を使用して .resx ファイルをバイナリ リソース (.resources) ファイルに変換し、アプリケーション アセンブリまたはサテライト アセンブリに埋め込みます。
ランタイム実行可能ファイルに .resx ファイルを埋め込んだり、サテライト アセンブリにコンパイルしたりすることはできません。 リソース ファイル ジェネレーター (Resgen.exe) を使用して、.resx ファイルをバイナリ リソース (.resources) ファイルに変換する必要があります。 結果の .resources ファイルは、アプリケーション アセンブリまたはサテライト アセンブリに埋め込むことができます。 詳細については、「 リソース ファイルの作成」を参照してください。
リソースを列挙する
場合によっては、特定のリソースではなく、すべてのリソースを .resx ファイルから取得することが必要になる場合があります。 これを行うには、.resx ファイル内のすべてのリソースの列挙子を提供する System.Resources.ResXResourceReader クラスを使用できます。 System.Resources.ResXResourceReader クラスはIDictionaryEnumeratorを実装します。このクラスは、ループの反復ごとに特定のリソースを表すDictionaryEntry オブジェクトを返します。 DictionaryEntry.Key プロパティはリソースのキーを返し、DictionaryEntry.Value プロパティはリソースの値を返します。
次の例では、前の例で作成した CarResources.resx ファイルの ResXResourceReader オブジェクトを作成し、リソース ファイルを反復処理します。 リソース ファイルで定義されている 2 つの Automobile
オブジェクトを System.Collections.Generic.List<T> オブジェクトに追加し、 SortedList オブジェクトに 6 つの文字列のうち 5 つを追加します。
SortedList オブジェクトの値はパラメーター配列に変換されます。これは、列見出しをコンソールに表示するために使用されます。
Automobile
プロパティ値もコンソールに表示されます。
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
特定のリソースを取得する
.resx ファイル内の項目を列挙するだけでなく、 System.Resources.ResXResourceSet クラスを使用して名前で特定のリソースを取得できます。 ResourceSet.GetString(String) メソッドは、名前付き文字列リソースの値を取得します。 ResourceSet.GetObject(String) メソッドは、名前付きオブジェクトまたはバイナリ データの値を取得します。 このメソッドは、(C# で) キャストする必要があるオブジェクト、または (Visual Basic では) 適切な型のオブジェクトに変換する必要があるオブジェクトを返します。
次の例では、フォームのキャプション文字列とアイコンをリソース名で取得します。 また、前の例で使用したアプリケーション定義の Automobile
オブジェクトを取得し、 DataGridView コントロールに表示します。
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
resx ファイルをバイナリの .resources ファイルに変換する
.resx ファイルを埋め込みバイナリ リソース (.resources) ファイルに変換すると、大きな利点があります。 .resx ファイルは、アプリケーションの開発中に読みやすく保守が容易ですが、完成したアプリケーションに含まれることはほとんどありません。 アプリケーションと共に配布される場合は、アプリケーション実行可能ファイルとそれに付随するライブラリとは別に、個別のファイルとして存在します。 これに対し、 .resources ファイルは、アプリケーションの実行可能ファイルとそれに付随するアセンブリに埋め込まれます。 また、ローカライズされたアプリケーションの場合、実行時に .resx ファイルに依存すると、開発者にリソース フォールバックを処理する責任が生まれます。 これに対し、埋め込み .resources ファイルを含むサテライト アセンブリのセットが作成されている場合、共通言語ランタイムはリソース フォールバック プロセスを処理します。
.resx ファイルを .resources ファイルに変換するには、次の基本的な構文を持つリソース ファイル ジェネレーター (resgen.exe) を使用します。
resgen.exe .resxFilename
結果は、.resx ファイルと同じルート ファイル名と .resources ファイル拡張子を持つバイナリ リソース ファイルです。 このファイルは、コンパイル時に実行可能ファイルまたはライブラリにコンパイルできます。 Visual Basic コンパイラを使用している場合は、次の構文を使用して、アプリケーションの実行可能ファイルに .resources ファイルを埋め込みます。
vbc filename .vb -resource: .resourcesFilename
C# を使用している場合、構文は次のようになります。
csc filename .cs -resource: .resourcesFilename
.resources ファイルは、アセンブリ リンカー (al.exe) を使用してサテライト アセンブリに埋め込むこともできます。このファイルには、次の基本的な構文があります。
al resourcesFilename -out: assemblyFilename
こちらも参照ください
.NET