読者です 読者をやめる 読者になる 読者になる

プログラミング C# - 翔ソフトウェア (Sho's)

C#/.NET/ソフトウェア開発など

列挙型 (enum) の列挙子の動的な取得など

今回は、列挙型 (enum) の列挙子の取得などについて。

■ 列挙型 (enum) の列挙子を動的なメソッド呼び出しの引数で渡したい

例えば、次のようなクラス ライブラリー (ClassLibrary.dll) があるとする。

// クラス ライブラリー側: ClassLibrary.dll
namespace ClassLibrary
{
    // 列挙型 (enum)
    public enum ItemKind
    {
        Book, Toy, Stationary
    }

    // クラス
    public class Item
    {
        // アイテムの種類 (型は列挙型の ItemKind)
        readonly ItemKind itemType;

        // コンストラクター (引数でアイテムの種類を指定)
        public Item(ItemKind itemType)
        { this.itemType = itemType; }
    }
}

そして、別のプロジェクトで、このクラス ライブラリーを動的に読み込んで使いたいとする。

例.

// クラス ライブラリーを動的に利用する側: Xxx.exe
using System;
using System.Reflection;

class Program
{
    static void Main()
    {
        // アセンブリ名を使ってクラス ライブラリーを動的に読み込み
        var assembly = Assembly.Load("ClassLibrary");
        // アセンブリ内のクラスの型情報を取得
        var itemType = assembly.GetType("ClassLibrary.Item");

        // ... 途中省略 ...
    }
}

ここで次のように、型情報 itemType を使って、インスタンスを生成させようとしてみる。

        // ... 途中省略 ...

        // アセンブリ名を使ってクラス ライブラリーを動的に読み込み
        var assembly = Assembly.Load("ClassLibrary");
        // アセンブリ内のクラスの型情報を取得
        var itemType = assembly.GetType("ClassLibrary.Item");

        // クラスの型情報を使って、クラスのインスタンスを生成
        dynamic item = Activator.CreateInstance(itemType, 0 /* ClassLibrary.ItemKind.Book の値 */);

        // ... 途中省略 ...

これは次のように、実行時エラーになる。
コンストラクターの引数の型が合っていないからだ。

実行時エラー その1

勿論、object にキャストしても実行時エラーの儘だ。

実行時エラー その2

だが、クラス ライブラリーを動的に読み込みたい訳なので、ClassLibrary.ItemKind.Book と書く訳にもいかない。

        // ... 途中省略 ...

        // クラスの型情報を使って、クラスのインスタンスを生成
        dynamic item = Activator.CreateInstance(itemType, ClassLibrary.ItemKind.Book); // コンパイル エラー

        // ... 途中省略 ...

こういう場合はどうすれば良いだろうか?

これは、次のように、列挙型 (enum) の型情報も取得して、そこから ClassLibrary.ItemKind.Book を生成してやれば良い。

        // ... 途中省略 ...

        // アセンブリ内の列挙型 (enum) の型情報をアセンブリから取得
        var itemKindType     = assembly.GetType("ClassLibrary.ItemKind");
        // enum の列挙オブジェクト ClassLibrary.ItemKind.Book を生成
        var itemKindTypeBook = Enum.Parse(itemKindType, "Book");

        // クラスの型情報を使って、クラスのインスタンスを生成
        dynamic item = Activator.CreateInstance(itemType, itemKindTypeBook);

        // ... 途中省略 ...

Enum.Parse メソッドを使って enum の列挙子名から列挙オブジェクトを生成するのがポイントだ。

■ 列挙型 (enum) の列挙子の名称を取得

列挙型 (enum) の型情報から全ての列挙子の名称を取得することもできる。

例えば、列挙型 (enum) ClassLibrary.ItemKind の全ての列挙子の名称を取得するには次のようにすれば良い。

        // ... 途中省略 ...

        // 列挙型 (enum) の全ての列挙子の名称を取得
        string[] itemKindTypeNames = Enum.GetNames(typeof(ClassLibrary.ItemKind));

        // ... 途中省略 ...

列挙子の名称が配列で得られる。即ち、ここから列挙子の数を取得することができることになる。

        // ... 途中省略 ...

        // 列挙型 (enum) の列挙子の数を取得
        int itemKindTypeLength = Enum.GetNames(typeof(ClassLibrary.ItemKind)).Length;

        // ... 途中省略 ...

Enum.GetTypes メソッドで、全ての列挙子オブジェクトを配列 (Array) で取得することもできるので、次のようにしても良い。

        // ... 途中省略 ...

        // 列挙型 (enum) の列挙子の数を取得
        int itemKindTypeLength = Enum.GetTypes(typeof(ClassLibrary.ItemKind)).Length;

        // ... 途中省略 ...