属性に格納されている情報の取得

カスタム属性を取得するプロセスは簡単です。まず、取得する属性のインスタンスを宣言します。次に、Attribute.GetCustomAttribute メソッドを使用して、取得する属性の値に新しい属性を初期化します。新しい属性が初期化されたら、そのプロパティを使用して値を取得できます。

重要

このトピックでは、実行コンテキストに読み込まれるコードの属性を取得する方法について説明します。リフレクション専用のコンテキストに読み込むコードの属性を取得するには、「方法 : リフレクションのみのコンテキストにアセンブリを読み込む」に示されているように、CustomAttributeData クラスを使用する必要があります。

ここでは、属性を取得する方法について説明します。

  • 属性の 1 つのインスタンスの取得。

  • 同じスコープに適用された属性の複数のインスタンスの取得。

  • 他のスコープに適用された属性の複数のインスタンスの取得。

属性の 1 つのインスタンスの取得

前のセクションで説明した DeveloperAttribute が、クラス レベルで MainApp クラスに適用されている例を次に示します。GetAttribute メソッドは、GetCustomAttribute を使用して、DeveloperAttribute に格納されている値をクラス レベルで取得し、コンソールに表示します。

using System;

[Developer("Joan Smith", "42", Reviewed = true)]
class MainApp
{
    public static void Main() 
    {
        //Call function to get and display the attribute.
        GetAttribute(typeof(MainApp));
    }
    
    public static void GetAttribute(Type t) 
    {
        
        
        //Get instance of the attribute.    
            DeveloperAttribute MyAttribute = (DeveloperAttribute) Attribute.GetCustomAttribute(t, typeof (DeveloperAttribute));
            
            if(null == MyAttribute)
            {
                Console.WriteLine("The attribute was not found.");
            }
            else
            {
                //Get the Name value.    
                Console.WriteLine("The Name Attribute is: {0}." , MyAttribute.Name);
                //Get the Level value.    
                Console.WriteLine("The Level Attribute is: {0}." , MyAttribute.Level);
                //Get the Reviewed value.
                Console.WriteLine("The Reviewed Attribute is: {0}." , MyAttribute.Reviewed);
            }
    }
}
Imports System

<Developer("Joan Smith", "42", Reviewed := True)> Class MainApp
    
    Public Shared Sub Main()
        'Call function to get and display the attribute.
        GetAttribute(GetType(MainApp))
    End Sub
    
    Public Shared Sub GetAttribute(t As Type)        
        
        'Get instance of the attribute.
        Dim MyAttribute As DeveloperAttribute = _
        CType(Attribute.GetCustomAttribute(t, GetType(DeveloperAttribute)), DeveloperAttribute)
        
        If MyAttribute Is Nothing Then
            Console.WriteLine("The attribute was not found.")
        Else
            'Get the Name value.
            Console.WriteLine("The Name Attribute is: {0}.", MyAttribute.Name)
            'Get the Level value.
            Console.WriteLine("The Level Attribute is: {0}.", MyAttribute.Level)
            'Get the Reviewed value.
            Console.WriteLine("The Reviewed Attribute is: {0}.", MyAttribute.Reviewed)
        End If
    End Sub
End Class

このプログラムは、実行されると次のテキストを表示します。

The Name Attribute is: Joan Smith.
The Level Attribute is: 42.
The Reviewed Attribute is: True.

属性が見つからない場合、GetCustomAttribute メソッドは MyAttribute を null 値に初期化します。この例では、MyAttribute をチェックして、属性が見つからない場合はユーザーに通知します。クラス スコープ内に DeveloperAttribute が見つからない場合は、コンソールに次のメッセージが表示されます。

The attribute was not found. 

この例では、属性の定義が現在の名前空間内にあることを想定しています。属性の定義が現在の名前空間内にないときは、属性の定義がある名前空間をインポートする必要があります。

同じスコープに適用された属性の複数のインスタンスの取得

前の例では、調べるクラスと検索する属性が GetCustomAttribute に渡されています。このコードが正常に機能するのは、属性の 1 つのインスタンスだけがクラス レベルで適用されているときです。属性の複数のインスタンスが同じクラス レベルで適用されている場合は、GetCustomAttribute メソッドによってすべての情報を取得することはできません。同じ属性の複数のインスタンスが同じスコープに適用されている場合は、Attribute.GetCustomAttributes を使用して、属性のすべてのインスタンスを配列に格納できます。たとえば、DeveloperAttribute の 2 つのインスタンスが同じクラスのクラス レベルで適用されている場合は、両方の属性で見つかる情報を表示するように GetAttribute メソッドを変更できます。ただし、同じレベルで複数の属性を適用するには、AttributeUsageAttributeAllowMultiple プロパティを true として属性を定義しておく必要があります。

GetCustomAttributes メソッドを使用して、指定したクラス内の DeveloperAttribute のすべてのインスタンスを参照する配列を作成する方法を次のコード例に示します。すべての属性の値は、コンソールに表示されます。

public static void GetAttribute(Type t)
{
    DeveloperAttribute[] MyAttribute =
    (DeveloperAttribute[]) Attribute.GetCustomAttributes(t, typeof (DeveloperAttribute));
    
    if(null == MyAttribute)
    {
        Console.WriteLine("The attribute was not found.");
    }
    else
    {
        for(int i = 0 ; i < MyAttribute.Length ; i++)
        {
            //Get the Name value.    
            Console.WriteLine("The Name Attribute is: {0}." , MyAttribute[i].Name);
            //Get the Level value.  
            Console.WriteLine("The Level Attribute is: {0}." , MyAttribute[i].Level);
            //Get the Reviewed value.
            Console.WriteLine("The Reviewed Attribute is: {0}.", MyAttribute[i].Reviewed);
        }
    }
}
Public Shared Sub GetAttribute(t As Type)
    Dim MyAttribute As DeveloperAttribute() = _
    CType(Attribute.GetCustomAttributes(t, GetType(DeveloperAttribute)), DeveloperAttribute())
       
    If MyAttribute Is Nothing Then
        Console.WriteLine("The attribute was not found.")
    Else
        Dim i As Integer
        For i = 0 To MyAttribute.Length - 1
            'Get the Name value. 
            Console.WriteLine("The Name Attribute is: {0}.", MyAttribute(i).Name)
            'Get the Level value.   
            Console.WriteLine("The Level Attribute is: {0}.", MyAttribute(i).Level)
            'Get the Reviewed value.
            Console.WriteLine("The Reviewed Attribute is: {0}.", MyAttribute(i).Reviewed)
        Next i
    End If
End Sub

属性が見つからない場合、このコードはユーザーに警告を発します。それ以外の場合は、DeveloperAttribute の両方のインスタンスに含まれている情報が表示されます。

ほかのスコープに適用された属性の複数のインスタンスの取得

GetCustomAttributes メソッドと GetCustomAttribute メソッドでは、クラス全体を検索してクラス内の属性のすべてのインスタンスを返すことはできません。これらのメソッドが一度に検索するのは、指定された 1 つのメソッドまたは 1 つのメンバだけです。クラスのメンバすべてに同じ属性が適用されていて、それらのメンバに適用されたすべての属性の値を取得するには、すべてのメソッドやメンバを個別に GetCustomAttributesGetCustomAttribute に渡す必要があります。

パラメータとしてクラスをとり、そのクラス レベルとそのクラスの各メソッドすべてについて DeveloperAttribute (前に定義されています) を検索するコード例を次に示します。

public static void GetAttribute(Type t) 
{
            
    DeveloperAttribute att;

    //Get the class-level attributes.
    
    //Put the instance of the attribute on the class level in the att object.
    att = (DeveloperAttribute) Attribute.GetCustomAttribute (t, typeof (DeveloperAttribute));
        
    if(null == att)
    {
        Console.WriteLine("No attribute in class {0}.\n", t.ToString());
    }
    else
    {
        Console.WriteLine("The Name Attribute on the class level is: {0}.", att.Name);
       Console.WriteLine("The Level Attribute on the class level is: {0}.", att.Level);
       Console.WriteLine("The Reviewed Attribute on the class level is: {0}.\n", att.Reviewed);
    }   

    //Get the method-level attributes.

    //Get all methods in this class, and put them
    //in an array of System.Reflection.MemberInfo objects.
    MemberInfo[] MyMemberInfo = t.GetMethods();

    //Loop through all methods in this class that are in the 
    //MyMemberInfo array.
    for(int i = 0; i < MyMemberInfo.Length; i++)
    {        
        att = (DeveloperAttribute) Attribute.GetCustomAttribute(MyMemberInfo[i], typeof (DeveloperAttribute));
        if(null == att)
        {
            Console.WriteLine("No attribute in member function {0}.\n" , MyMemberInfo[i].ToString());
        }
        else
        {
            Console.WriteLine("The Name Attribute for the {0} member is: {1}.", MyMemberInfo[i].ToString(), att.Name);
            Console.WriteLine("The Level Attribute for the {0} member is: {1}.", MyMemberInfo[i].ToString(), att.Level);
            Console.WriteLine("The Reviewed Attribute for the {0} member is: {1}.\n", MyMemberInfo[i].ToString(), att.Reviewed);
        }        
    }
}
Public Shared Sub GetAttribute(t As Type)
    
    Dim att As DeveloperAttribute
    
    'Get the class-level attributes.
    'Put the instance of the attribute on the class level in the att object.
    att = CType(Attribute.GetCustomAttribute(t, GetType(DeveloperAttribute)), DeveloperAttribute)
    
    If att Is Nothing Then
        Console.WriteLine("No attribute in class {0}.", t.ToString())
        Console.WriteLine()
    Else
        Console.WriteLine("The Name Attribute on the class level is: {0}.", att.Name)
        Console.WriteLine("The Level Attribute on the class level is: {0}.", att.Level)
        Console.WriteLine("The Reviewed Attribute on the class level is: {0}.", att.Reviewed)
        Console.WriteLine()
    End If
    
    'Get the method-level attributes.
    'Get all methods in this class and put them
    'in an array of System.Reflection.MemberInfo objects.
    Dim MyMemberInfo As MemberInfo() = t.GetMethods()
    
    'Loop through all methods in this class that are in the 
    'MyMemberInfo array.
    Dim i As Integer
    For i = 0 To MyMemberInfo.Length - 1
        att = CType(Attribute.GetCustomAttribute(MyMemberInfo(i), GetType(DeveloperAttribute)), DeveloperAttribute)
        If att Is Nothing Then
            Console.WriteLine("No attribute in member function {0}.", MyMemberInfo(i).ToString())
            Console.WriteLine()
        Else
            Console.WriteLine("The Name Attribute for the {0} member is: {1}.", MyMemberInfo(i).ToString(), att.Name)
            Console.WriteLine("The Level Attribute for the {0} member is: {1}.", MyMemberInfo(i).ToString(), att.Level)
            Console.WriteLine("The Reviewed Attribute for the {0} member is: {1}.", MyMemberInfo(i).ToString(), att.Reviewed)
            Console.WriteLine()
        End If
    Next i
End Sub

メソッド レベルまたはクラス レベルで DeveloperAttribute のインスタンスが見つからない場合、GetAttribute メソッドは属性が見つからなかったことをユーザーに通知し、属性が含まれないメソッド名またはクラス名を表示します。属性が見つかった場合は、NameLevelReviewed の各フィールドがコンソールに表示されます。

渡されたクラス内の各のメソッドとメンバを取得するには、Type クラスのメンバを使用します。この例では、最初に Type オブジェクトを問い合わせて、クラス レベルの属性情報を取得しています。次に、Type.GetMethods を使用して、すべてのメソッドのインスタンスを System.Reflection.MemberInfo オブジェクトの配列に格納し、メソッド レベルの属性情報を取得します。また、Type.GetProperties メソッドを使用してプロパティ レベルの属性を調べることも、Type.GetConstructors メソッドを使用してコンストラクタ レベルの属性を調べることもできます。

参照

関連項目

System.Type
Attribute.GetCustomAttribute
Attribute.GetCustomAttributes

その他の技術情報

属性を使用したメタデータの拡張