bucket-sort logo bucket-sort

プログラミングとインフラエンジニアリングの覚え書き

  • Posts
  • About
  • Contact
  1. Home
  2. All Posts
  3. [C#] リフレクションで型の中身を調べる

[C#] リフレクションで型の中身を調べる

Jul 6, 2026 C# , .NET bucket-sort

前回は、型メタデータと System.Type の基本を見ました。

今回は、リフレクションを使って型の中身を詳しく調べます。
メソッド、フィールド、プロパティ、インターフェイス、静的型、ジェネリック型、引数と戻り値を確認する、小さなメタデータビューアを作っていきます。

調査対象の型を用意する

まず、リフレクションで調べるための型を用意します。

namespace ReflectionViewerSample;

public interface IDriveable
{
    void Drive(int distance);
}

public class Car : IDriveable
{
    private int currentSpeed;

    public string Name { get; }
    public int CurrentSpeed => currentSpeed;

    public Car(string name)
    {
        Name = name;
    }

    public void Accelerate(int delta)
    {
        currentSpeed += delta;
    }

    public void Drive(int distance)
    {
        Console.WriteLine($"{Name} drives {distance}km.");
    }

    public override string ToString()
    {
        return $"{Name}: {CurrentSpeed}km/h";
    }
}

この型には、フィールド、プロパティ、コンストラクター、メソッド、インターフェイス実装が含まれています。

メソッドを調べる

GetMethods() を使うと、型に定義されているメソッドを取得できます。

using System.Reflection;
using ReflectionViewerSample;

Type type = typeof(Car);

MethodInfo[] methods = type.GetMethods(
    BindingFlags.Public |
    BindingFlags.Instance |
    BindingFlags.DeclaredOnly);

foreach (MethodInfo method in methods)
{
    Console.WriteLine($"{method.ReturnType.Name} {method.Name}");
}

BindingFlags は、どのメンバーを取得するかを指定するためのフラグです。

  • Public: public メンバーを対象にする
  • NonPublic: private や protected なども対象にする
  • Instance: インスタンスメンバーを対象にする
  • Static: 静的メンバーを対象にする
  • DeclaredOnly: その型で宣言されたメンバーだけを対象にする

DeclaredOnly を外すと、基底クラスから継承されたメソッドも含まれます。

フィールドとプロパティを調べる

フィールドは GetFields()、プロパティは GetProperties() で取得できます。

using System.Reflection;
using ReflectionViewerSample;

Type type = typeof(Car);

Console.WriteLine("フィールド:");
foreach (FieldInfo field in type.GetFields(
    BindingFlags.Public |
    BindingFlags.NonPublic |
    BindingFlags.Instance |
    BindingFlags.DeclaredOnly))
{
    Console.WriteLine($"{field.FieldType.Name} {field.Name}");
}

Console.WriteLine("プロパティ:");
foreach (PropertyInfo property in type.GetProperties(
    BindingFlags.Public |
    BindingFlags.Instance |
    BindingFlags.DeclaredOnly))
{
    Console.WriteLine($"{property.PropertyType.Name} {property.Name}");
}

プロパティは C# の文法上はフィールドに似て見えますが、メタデータ上はアクセサーメソッドを持つメンバーとして扱われます。

実装しているインターフェイスを調べる

GetInterfaces() を使うと、型が実装しているインターフェイスを取得できます。

using ReflectionViewerSample;

Type type = typeof(Car);

foreach (Type interfaceType in type.GetInterfaces())
{
    Console.WriteLine(interfaceType.FullName);
}

プラグイン探索では、この仕組みがよく使われます。
「特定のインターフェイスを実装している型を探す」ことで、外部 DLL から実行対象を見つけられます。

Type contractType = typeof(IDriveable);

bool canDrive = contractType.IsAssignableFrom(typeof(Car));

Console.WriteLine(canDrive);

IsAssignableFrom() は、「指定した型として扱えるか」を判定するために便利です。

その他の基本情報を表示する

型には、種類を判定するためのプロパティがたくさんあります。

using ReflectionViewerSample;

Type type = typeof(Car);

Console.WriteLine($"名前: {type.FullName}");
Console.WriteLine($"クラス: {type.IsClass}");
Console.WriteLine($"抽象型: {type.IsAbstract}");
Console.WriteLine($"public: {type.IsPublic}");
Console.WriteLine($"sealed: {type.IsSealed}");
Console.WriteLine($"値型: {type.IsValueType}");
Console.WriteLine($"列挙型: {type.IsEnum}");

これらを組み合わせると、型の性質を実行時に分類できます。

静的型を調べる

C# の static class は、メタデータ上では abstract かつ sealed な型として表現されます。

namespace ReflectionViewerSample;

public static class Calculator
{
    public static int Add(int x, int y) => x + y;
}
using ReflectionViewerSample;

Type type = typeof(Calculator);

Console.WriteLine(type.IsAbstract);
Console.WriteLine(type.IsSealed);

両方が true なら、C# の静的クラスとして定義された可能性があります。

静的メソッドを取得するには、BindingFlags.Static を指定します。

foreach (var method in type.GetMethods(
    BindingFlags.Public |
    BindingFlags.Static |
    BindingFlags.DeclaredOnly))
{
    Console.WriteLine(method.Name);
}

ジェネリック型を調べる

ジェネリック型かどうかは IsGenericType で判定できます。

Type type = typeof(Dictionary<string, int>);

Console.WriteLine(type.IsGenericType);
Console.WriteLine(type.GetGenericTypeDefinition());

foreach (Type argument in type.GetGenericArguments())
{
    Console.WriteLine(argument.FullName);
}

Dictionary<string, int> のように型引数が具体化された型では、GetGenericArguments() で string と int を取得できます。

未構築のジェネリック型を扱う場合は、次のように書きます。

Type openType = typeof(List<>);

Console.WriteLine(openType.IsGenericTypeDefinition);

このあたりは、DI コンテナーが IRepository<T> のような型を登録・解決するときにも関係します。

メソッドの引数と戻り値を調べる

MethodInfo から、戻り値や引数の情報を取得できます。

using System.Reflection;
using ReflectionViewerSample;

Type type = typeof(Car);
MethodInfo? method = type.GetMethod(nameof(Car.Accelerate));

if (method != null)
{
    Console.WriteLine($"戻り値: {method.ReturnType.Name}");

    foreach (ParameterInfo parameter in method.GetParameters())
    {
        Console.WriteLine($"引数: {parameter.ParameterType.Name} {parameter.Name}");
    }
}

この仕組みを使うと、API ドキュメント生成、コマンド自動登録、プラグインの検証などができます。

簡易メタデータビューアを作る

ここまでの内容をまとめて、型情報を表示する関数を作ります。

using System.Reflection;

static void PrintMetadata(Type type)
{
    Console.WriteLine($"型: {type.FullName}");
    Console.WriteLine($"アセンブリ: {type.Assembly.GetName().Name}");
    Console.WriteLine($"基底型: {type.BaseType?.FullName}");
    Console.WriteLine();

    Console.WriteLine("インターフェイス:");
    foreach (Type interfaceType in type.GetInterfaces())
    {
        Console.WriteLine($"  {interfaceType.FullName}");
    }

    Console.WriteLine("プロパティ:");
    foreach (PropertyInfo property in type.GetProperties())
    {
        Console.WriteLine($"  {property.PropertyType.Name} {property.Name}");
    }

    Console.WriteLine("メソッド:");
    foreach (MethodInfo method in type.GetMethods(
        BindingFlags.Public |
        BindingFlags.Instance |
        BindingFlags.Static |
        BindingFlags.DeclaredOnly))
    {
        string parameters = string.Join(", ",
            method.GetParameters().Select(p => $"{p.ParameterType.Name} {p.Name}"));

        Console.WriteLine($"  {method.ReturnType.Name} {method.Name}({parameters})");
    }
}

使い方です。

PrintMetadata(typeof(ReflectionViewerSample.Car));
PrintMetadata(typeof(Dictionary<string, int>));

型を文字列で受け取るようにすれば、簡単な診断ツールにもできます。

Console.Write("型名を入力してください: ");
string? typeName = Console.ReadLine();

Type? type = Type.GetType(typeName ?? "");

if (type == null)
{
    Console.WriteLine("型が見つかりません。");
}
else
{
    PrintMetadata(type);
}

まとめ

リフレクションを使うと、型のメソッド、フィールド、プロパティ、インターフェイス、ジェネリック引数などを実行時に調べられます。

この技術は、単なる調査用ではありません。
プラグイン発見、コマンド自動登録、DI、属性駆動の設定、テスト実行など、アプリケーションを拡張しやすくする仕組みの裏側でよく使われています。

次回は、外部アセンブリを動的に読み込み、型を探して実行する「遅延バインディング」の考え方へ進みます。

C# .NET リフレクション System.Reflection メタデータ ジェネリック
← [C#] 型メタデータとリフレクションの基礎を理解する [C#] 外部アセンブリを読み込み実行時に型を呼び出す →

Related Posts

  • [C#] 属性でコードに意味を与える Jul 8, 2026
  • [C#] 型メタデータとリフレクションの基礎を理解する Jul 5, 2026
  • [C#] プラグインで拡張できるアプリケーションを設計する Jul 9, 2026
  • [C#] 外部アセンブリを読み込み実行時に型を呼び出す Jul 7, 2026

Table of Contents

  • 調査対象の型を用意する
  • メソッドを調べる
  • フィールドとプロパティを調べる
  • 実装しているインターフェイスを調べる
  • その他の基本情報を表示する
  • 静的型を調べる
  • ジェネリック型を調べる
  • メソッドの引数と戻り値を調べる
  • 簡易メタデータビューアを作る
  • まとめ

Recent Posts

  • [C#] プラグインで拡張できるアプリケーションを設計する Jul 9, 2026
  • [C#] 属性でコードに意味を与える Jul 8, 2026
  • [C#] 外部アセンブリを読み込み実行時に型を呼び出す Jul 7, 2026
  • [C#] リフレクションで型の中身を調べる Jul 6, 2026
  • [C#] 型メタデータとリフレクションの基礎を理解する Jul 5, 2026

Categories

  • C#120
  • .NET119
  • AWS27
  • Laravel16
  • Linux15
  • MySQL9
  • Apache8
  • PHP8
  • DynamoDB6
  • セキュリティ6
  • Nginx5
  • WordPress4
  • インフラ4
  • Hugo3
  • .NET Framework1
  • Aurora1
  • Diagnostics1
  • Filament1
  • Git1
  • SQS1

Tags

  • C#
  • .NET
  • AWS
  • Laravel
  • コレクション
  • PHP
  • セキュリティ
  • MySQL
  • Linux
  • パフォーマンス
  • Apache
  • System.Collections.Generic
  • デリゲート
  • Code Snippet
  • DynamoDB
  • LINQ
  • NoSQL
  • PHP-FPM
  • RDS
  • System.Collections
  • Windows
  • メモリ管理
  • リフレクション
  • DoS
  • Nginx
  • WordPress
  • メタデータ
  • ラムダ式
  • 監視
  • 設計
  • Amazon Linux 2023
  • Delegate
  • Docker
  • IDisposable
  • Ipset
  • Iptables
  • LINQ to Objects
  • OPCache
  • Pointer
  • Reflection
  • System.Collections.Specialized
  • Unsafe
  • Webサーバー
  • インターフェース
  • オブジェクト指向
  • クラス設計
  • デザインパターン
  • パターンマッチング
  • ポインター
  • 継承
Powered by Hugo & Explore Theme.