C#のリフレクション機能を使用すると、クラスだけでなくメソッドに対しても、どのような属性(Attribute)が付与されているかを実行時に調査できます。
これは、デバッグ時にメソッドのメタデータを確認したり、独自のフレームワークで特定の属性が付いたメソッドだけを抽出して実行したりする際に役立ちます。
目次
メソッド属性の取得実装
以下のサンプルコードでは、Output メソッドに付与された複数の属性(DebuggerStepThrough や Conditional)を GetCustomAttributes メソッドですべて取得し、その内容を表示しています。
サンプルコード
using System;
using System.Diagnostics; // DebuggerStepThrough, Conditional用
using System.Reflection;
public class Program
{
public static void Main()
{
// 1. 対象の型情報を取得
Type type = typeof(MySample);
// 2. 調査したいメソッド情報を取得
// nameofを使うことで、リファクタリング時の名前変更に対応できます
MethodInfo method = type.GetMethod(nameof(MySample.Output));
if (method != null)
{
Console.WriteLine($"メソッド '{method.Name}' に付与されている属性一覧:\n");
// 3. すべてのカスタム属性を取得
// 引数に true を渡すと、継承された属性も含めて取得します
object[] attributes = method.GetCustomAttributes(inherit: true);
foreach (var attr in attributes)
{
// 属性クラスの ToString() が呼ばれ、型名などが表示されます
Console.WriteLine($"- {attr}");
}
}
}
}
// サンプル用クラス
public class MySample
{
// 複数の属性を付与
// DebuggerStepThrough: デバッガでステップインしないようにする
// Conditional: 特定のシンボルが定義されている場合のみコンパイルに含める
[DebuggerStepThrough]
[Conditional("DEBUG_TRACE")]
public void Output(double num)
{
Console.Write($"num = {num}");
}
}
実行結果
メソッド 'Output' に付与されている属性一覧:
- System.Diagnostics.DebuggerStepThroughAttribute
- System.Diagnostics.ConditionalAttribute
解説と技術的なポイント
1. GetCustomAttributes メソッド
MethodInfo オブジェクトに対してこのメソッドを呼び出すと、そのメソッドに適用されているすべての属性インスタンスを object[](または Attribute[])として取得できます。
- 引数なし: そのメンバーで定義されている属性のみを取得します。
- 引数 (bool inherit):
trueを指定すると、オーバーライドされたメソッドの場合に親クラスのメソッドの属性も探索対象に含めます。
2. 特定の属性のみを取得したい場合
すべての属性ではなく、特定の属性(例えば ConditionalAttribute だけ)を取得したい場合は、ジェネリック版の拡張メソッドを使用するのがスマートです。
// 特定の属性を取得(存在しない場合は空の配列が返る)
var conditionalAttrs = method.GetCustomAttributes<ConditionalAttribute>();
3. メタデータの活用
フレームワーク開発(例:ユニットテストランナーやWeb APIルーティング)では、「特定の属性が付いたメソッドを探し出し、その属性に書かれた設定値(URLやタイムアウト時間など)に基づいて処理を実行する」というパターンが頻繁に使われます。今回の GetCustomAttributes はその基礎となる技術です。
