DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

型に指定した名前のメンバがあるか調べる

ある型(クラス、値型、配列、インターフェイス、ポインタ、列挙体)のすべてのメンバを取得する方法は、「型のすべてのメンバを取得する」で紹介しました。

ある型の指定した名前のメンバを取得するには、TypeクラスのGetMemberメソッドを使います。このとき、メンバの名前、メンバ型(プロパティ、メソッド、フィールドなど)、BindingFlags(詳しくはこちら)を指定することができます。

以下に、Stringクラスの"To"で始まる非静的なパブリックメソッドを検索する例を示します。

VB.NET
コードを隠すコードを選択
'Imports System.Reflection
'がソースファイルの一番上に書かれているものとする

'StringクラスのTypeオブジェクトを取得する
Dim t As Type = GetType(System.String)

'"To"ではじまるメソッドを検索する
'IgnoreCaseにより、大文字小文字を区別しないで検索
Dim members As MemberInfo() = t.GetMember( _
    "To*", MemberTypes.Method, _
    BindingFlags.Public Or BindingFlags.Instance Or _
    BindingFlags.DeclaredOnly Or BindingFlags.IgnoreCase)

Dim m As MemberInfo
For Each m In members
    'メンバの名前を表示する
    Console.WriteLine(m.Name)
Next
C#
コードを隠すコードを選択
//using System.Reflection;
//がソースファイルの一番上に書かれているものとする

//StringクラスのTypeオブジェクトを取得する
Type t = typeof(System.String);

//"To"ではじまるメソッドを検索する
//IgnoreCaseにより、大文字小文字を区別しないで検索
MemberInfo[] members = t.GetMember("To*",
    MemberTypes.Method,
    BindingFlags.Public | BindingFlags.Instance |
    BindingFlags.DeclaredOnly | BindingFlags.IgnoreCase);
foreach (MemberInfo m in members)
{
    //メンバの名前を表示する
    Console.WriteLine(m.Name);
}

実行した結果は次のようになります。

ToString
ToString
ToCharArray
ToCharArray
ToLower
ToLower
ToUpper
ToUpper

GetProperty、GetMethod、GetField、GetInterface、GetEvent、GetNestedTypeメソッド

型のプロパティ、メソッド、フィールド、コンストラクタ、インターフェイス、イベント、入れ子になっている型を検索するには、それぞれ、GetProperty、GetMethod、GetField、GetInterface、GetEvent、GetNestedTypeメソッドを使用します。

次にGetMethodメソッドを使用した例を示します。ここでは、StringクラスにConcatという名前でパラメータが(string, string)の静的パブリックメソッドがあるか検索しています。ちなみにGetMethodメソッドを呼び出したとき、複数のメソッドが見つかった時は、例外AmbiguousMatchExceptionがスローされます。

VB.NET
コードを隠すコードを選択
'Imports System.Reflection
'がソースファイルの一番上に書かれているものとする

'StringクラスのTypeオブジェクトを取得する
Dim t As Type = GetType(System.String)

'Concatという名前でパラメータが(string, string)の
'静的パブリックメソッドを探す
Dim method As MethodInfo = t.GetMethod("Concat", _
    BindingFlags.Public Or BindingFlags.Static, _
    Nothing, _
    New Type() {GetType(String), GetType(String)}, _
    Nothing)

'見つかった時、名前を表示
If Not (method Is Nothing) Then
    Console.WriteLine(method.Name)
Else
    Console.WriteLine("見つかりませんでした。")
End If
C#
コードを隠すコードを選択
//using System.Reflection;
//がソースファイルの一番上に書かれているものとする

//StringクラスのTypeオブジェクトを取得する
Type t = typeof(System.String);

//Concatという名前でパラメータが(string, string)の
//静的パブリックメソッドを探す
MethodInfo method = t.GetMethod("Concat",
    BindingFlags.Public | BindingFlags.Static,
    null,
    new Type[] {typeof(string), typeof(string)},
    null);

//見つかった時、名前を表示
if (method != null)
{
    Console.WriteLine(method.Name);
}
else
{
    Console.WriteLine("見つかりませんでした。");
}

FindMembersメソッドを使用する方法

TypeクラスのGetMemberメソッド以外にメンバを検索する方法として、FindMembersメソッドを使う方法もあります。FindMembersメソッドはMemberFilterデリゲートにより検索方法を指定できるため、より柔軟な検索ができます。

次にFindMembersメソッドを使って、Stringクラスのメソッドのうち、"Index"という文字列の入っているものを取得しています。

VB.NET
コードを隠すコードを選択
'Imports System.Reflection
'がソースファイルの一番上に書かれているものとする

Class MainClass
    'エントリポイント
    Overloads Shared Sub Main()
        'StringクラスのTypeオブジェクトを取得する
        Dim t As Type = GetType(System.String)

        '"Index"という文字列の入っているメソッドを探す
        Dim members As MemberInfo() = t.FindMembers( _
            MemberTypes.Method, _
            BindingFlags.Public Or BindingFlags.Instance, _
            New MemberFilter(AddressOf MemberFilterDelegate), _
            "Index")

        '見つかったメソッド名を表示する
        Dim m As MemberInfo
        For Each m In members
            Console.WriteLine(m.Name)
        Next
    End Sub

    'FindMembersで使用するMemberFilterデリゲート
    Public Shared Function MemberFilterDelegate( _
            ByVal m As MemberInfo, _
            ByVal filterCriteria As Object) As Boolean
        Dim filter As String = CStr(filterCriteria)

        'メンバ名にfilterCriteriaが入っているときはTrueを返す
        If m.Name.IndexOf(filter) < 0 Then
            Return False
        Else
            Return True
        End If
    End Function
End Class
C#
コードを隠すコードを選択
//using System.Reflection;
//がソースファイルの一番上に書かれているものとする

class MainClass
{
    //エントリポイント
    static void Main(string[] args)
    {
        //StringクラスのTypeオブジェクトを取得する
        Type t = typeof(System.String);

        //"Index"という文字列の入っているメソッドを探す
        MemberInfo[] members = t.FindMembers(MemberTypes.Method,
            BindingFlags.Public | BindingFlags.Instance,
            new MemberFilter(MemberFilterDelegate),
            "Index");

        //見つかったメソッド名を表示する
        foreach (MemberInfo m in members)
        {
            Console.WriteLine(m.Name);
        }
    }

    //FindMembersで使用するMemberFilterデリゲート
    public static bool MemberFilterDelegate(
        MemberInfo m, object filterCriteria)
    {
        string filter = (string) filterCriteria;
        
        //メンバ名にfilterCriteriaが入っているときはTrueを返す
        if(m.Name.IndexOf(filter) < 0)
            return false;
        else 
            return true;
    }
}

FindMembersメソッドで使用するMemberFilterデリゲートにはすでに用意されているものがいくつかあります。

TypeクラスのFilterNameフィールドは、指定した名前のメンバがあるか、ワイルドカード"*"を使って検索するために使用できます。FilterNameIgnoreCaseフィールドも同様ですが、FilterNameが大文字と小文字を区別して検索するのに対して、FilterNameIgnoreCaseは区別しません。

また、FilterAttributeフィールドは、FieldAttributes、MethodAttributes、またはMethodImplAttributes列挙体を指定し、一致するメンバを検索するために使用できます。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • コードの先頭に記述されている「Imports ??? がソースファイルの一番上に書かれているものとする」(C#では、「using ???; がソースファイルの一番上に書かれているものとする」)の意味が分からないという方は、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。