2006 年 7 月 12 日 20 時 48 分

NET のリソース


このアーカイブは同期化されません。 mixi の日記が更新されても、このアーカイブには反映されません。


現在、言語依存の文字列をそのままリテラルとして
ソースコードに含めている部分が何箇所かある。

一般的にこういう文字列をソースに残すのは推奨されない。
文字列は色々な場所に散らばるので、
ソースコードの保守が難しくなる。

また、ロジックを書く開発者と、
文言を書く開発者の分業が難しくなるという側面もある。
文言を変更するだけで、ソースごと
再度コンパイルを行う必要があるからだ。

こういった問題に対処するため、
.NET にはリソースという仕組みがある。
リソースはアセンブリに含むことができる任意のデータだ。

旧来の Windows にも .res と呼ばれるリソースがあったが、
プロジェクトのリソースを 1 ファイルで管理するため、
そこに全てのデータ等を集約する必要があった。

それに比べて NET のリソースは柔軟性が高い。

リソースを追加するためには、
プロジェクトに適当なファイルを追加し、
ファイルのプロパティの「ビルドアクション」を
「埋め込まれたリソース」にするだけだ。

この状態でビルドすると、アセンブリ内にデータが追加され、
これらの埋め込まれたリソースは、クラス等と同じように、
名前空間を使って名前付けが行われる。

例えば、Column フォルダに「logo.bmp」を作った場合、
「LoaferShellEx.Column.logo.bmp」という名前となる。
(これは C# でビルドした場合の話だ)

プログラムからは、Assembly クラスの
GetManifestResourceStream メソッドに名前を指定すれば、
バイト Stream として読み出しが出来るようになる。

    string name = "LoaferShellEx.Column.logo.bmp";
    Assembly self = Assembly.GetExecutingAssembly();
    Stream data = self.GetManifestResourceStream(name);

これは、任意のバイナリデータを格納するのに適している。

でも、文字列などを上の方法で格納するのは非現実的だ。
個別にファイル化し、Stream で読み出すのは大変である。
そのため、NET には、従来のような集合型リソースもある。
それは、.resources というファイルだ。

.resources も、他のリソースと同じように埋め込まれた
ただのバイナリファイルなのだが、
.resources を使えば、複数のリソースをまとめて
1 つのリソースとして扱うことができる。
そのため、関連するリソースを集約させることができる。

.resources は、名前と値と型の組み合わせとして、
内部に複数のリソースを格納することができる。
項目ごとに厳密に型を指定する点も特徴だ。

.resources はバイト Stream として読み出すのではなく、
ResourceManager クラスを経由して読み出すことで、
プログラムからリソースを読み出す際に、
クラスのインスタンスとして取り出すことができるのだ。

例えば、Column フォルダに「Strings.resources」を作り、
その中に「logo」という名前で画像データを入れた場合、
「LoaferShellEx.Column.Strings.resources」ができ、
その内部に、「logo」という名前を持つリソースが含まれる。
(C# でビルドした場合)

プログラムからは、ResourceManager クラスを作成し、
GetObject メソッドを呼び出してインスタンスを得る。

    string name = "LoaferShellEx.Column.Strings";
    string key = "logo";
    Assembly self = Assembly.GetExecutingAssembly();
    ResourceManager res = new ResourceManager(name, self);
    Bitmap bmp = (Bitmap)res.GetObject("logo");

明日は、この仕組みを使って、
文字列をリソースに切り離す作業をしてみよう。



Copyright (c) 1994-2007 Project Loafer. All rights reserved.