Typeクラス

型の宣言の情報を表すクラスです。

プロパティ

プロパティ 内容
string FullName 型の完全修飾名 (fully qualified name)
bool IsArray 型が配列であるならば、true。int[]はtrueだが、ArrayやIEnumerable<T>はfalseとなる Remarks - Type.IsArray Property (System) | Microsoft Learn
bool IsClass 型がクラスまたはデリゲートならば、true
     
Type type = typeof(int);
string s1 = type.Namespace; // "System"
string s2 = type.Name;      // "Int32"
string s3 = type.FullName;  // "System.Int32"
string s4 = type.AssemblyQualifiedName; // "System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"

メソッド

戻り値の型 メソッド 機能
Type MakeArrayType() 1次元配列として表されるTypeオブジェクトを得られる
Type MakeByRefType() ref修飾子を付けて渡されるときのTypeオブジェクトを得られる

つまりType.GetType("System.Object&")として得られるTypeを、typeof(System.Object).MakeByRefType()で得られる

     

メンバの情報の取得

たとえば次のような型があるとすると、

public class MyClass
{
    private int field1;
    public int field2;

    private void Method1(int a, int b) { }
    public void Method2(int a, int b) { }

    public int Property1 { get; }
}

この型のTypeから、メンバの情報を取得できます。

public MemberInfo[] GetMembers()
Type.GetMembers メソッド (System) | Microsoft Learn

返されるメンバは、アルファベット順や宣言順などの特定の順番とはなりません。Remarks - Type.GetMembers Method (System)

Type type = typeof(MyClass);

MemberInfo[] memberInfos = type.GetMembers(); // すべてのパブリック メンバ

ConstructorInfo[] ConstructorInfos = type.GetConstructors(); // すべてのパブリック コンストラクタ
FieldInfo[] fieldInfos = type.GetFields();           // すべてのパブリック フィールド
MethodInfo[] methodInfos = type.GetMethods();        // すべてのパブリック メソッド
PropertyInfo[] propertyInfos = type.GetProperties(); // すべてのパブリック プロパティ
EventInfo[] eventInfo= type.GetEvents();             // すべてのパブリック イベント

Console.Write(fieldInfos[0].Name); // field2

GetInterfaces()

実装または継承されている、すべてのインターフェイスを取得できます。

public abstract Type[] GetInterfaces ();
typeof(int).GetInterfaces()

// [0]: {Name = "IComparable" FullName = "System.IComparable"}
// [1]: {Name = "IFormattable" FullName = "System.IFormattable"}
// [2]: {Name = "IConvertible" FullName = "System.IConvertible"}
// [3]: {Name = "IComparable`1" FullName = "System.IComparable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}
// [4]: {Name = "IEquatable`1" FullName = "System.IEquatable`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}

GetConstructor()

バインディング制約を指定して、コンストラクタを検索できます。

[System.Runtime.InteropServices.ComVisible(true)]
public System.Reflection.ConstructorInfo GetConstructor (
    System.Reflection.BindingFlags bindingAttr, // バインディング制約
    System.Reflection.Binder binder,
    Type[] types,
    System.Reflection.ParameterModifier[] modifiers
    );
GetConstructor(BindingFlags, Binder, Type[], ParameterModifier[]) - Type.GetConstructor メソッド (System) | Microsoft Learn
Type type = typeof(MyClass);

// 引数のないコンストラクタの呼び出し
ConstructorInfo info1 = type.GetConstructor(
    BindingFlags.Instance | BindingFlags.Public,
    null,
    Type.EmptyTypes,
    null);
MyClass myClass1 = (MyClass)info1.Invoke(null);

// 引数が(int, double)であるコンストラクタの呼び出し
ConstructorInfo info2 = type.GetConstrctor(
    BindingFlags.Instance | BindingFlags.Public,
    null,
    new[] { typeof(int), typeof(double) },
    null);
MyClass myClass2 = (MyClass)info2.Invoke(new object[] { 1, 2.0 });

Activator.CreateInstance()ならば、直接インスタンスを作成できます。

public static object CreateInstance (
    Type type,
    System.Reflection.BindingFlags bindingAttr, // バインディング制約
    System.Reflection.Binder binder,
    object[] args,
    System.Globalization.CultureInfo culture
    );
CreateInstance(Type, BindingFlags, Binder, Object[], CultureInfo) - Activator.CreateInstance メソッド (System) | Microsoft Learn
// 引数のないコンストラクタの呼び出し
MyClass obj1 = (MyClass)Activator.CreateInstance(
    type,
    BindingFlags.Instance | BindingFlags.Public,
    null,
    null,
    CultureInfo.InvariantCulture);

// 引数のあるコンストラクタの呼び出し
MyClass obj2 = (MyClass)Activator.CreateInstance(
    type,
    BindingFlags.Instance | BindingFlags.Public,
    null,
    new object[] { 1, 2.0 },
    CultureInfo.InvariantCulture);

GetField()

バインディング制約を指定して、フィールドを検索できます。

public abstract System.Reflection.FieldInfo GetField (
    string name,                               // フィールドの名前
    System.Reflection.BindingFlags bindingAttr // バインディング制約
    );
GetField(String, BindingFlags) - Type.GetField メソッド (System) | Microsoft Learn

取得時にBindingFlags.NonPublicを指定すると非パブリックなメンバの情報も取得でき、これを介すとprivateなメンバへもアクセスできます。そして設定はFieldInfo.SetValue()、取得はFieldInfo.GetValue()で行えます。

このとき対象がインスタンスのフィールドならばそのインスタンスを、クラスのそれならばnullを渡します。

MyClass obj = new MyClass();
// obj.field1 = 1; // error CS0122: 'MyClass.field1' はアクセスできない保護レベルになっています

Type type = typeof(MyClass);
FieldInfo field1 = type.GetField("field1", BindingFlags.NonPublic | BindingFlags.Instance);

field1.SetValue(obj, 1); // ok
int value = (int)field1.GetValue(obj);

バインディング制約は、アクセス対象の修飾子によって下表のように指定します。

アクセス対象の修飾子 バインディング制約
private BindingFlags.NonPublic | BindingFlags.Instance
private static BindingFlags.NonPublic | BindingFlags.Static

GetProperty()

バインディング制約を指定して、プロパティを検索できます。

public System.Reflection.PropertyInfo GetProperty (
    string name,
    System.Reflection.BindingFlags bindingAttr // バインディング制約
    );
GetProperty(String, BindingFlags) - Type.GetProperty メソッド (System) | Microsoft Learn

GetMethod()

バインディング制約を指定して、メソッドを検索できます。

public System.Reflection.MethodInfo GetMethod (
    string name,
    System.Reflection.BindingFlags bindingAttr // バインディング制約
    );
GetMethod(String, BindingFlags) - Type.GetMethod メソッド (System) | Microsoft Learn
Type type = typeof(MyClass);
MethodInfo method1 = type.GetMethod("Method1", BindingFlags.NonPublic | BindingFlags.Instance);

MyClass obj = new MyClass();
method1.Invoke(obj, new object[] { 1, 2 });

メソッドに同じバインディング制約のオーバーロードがあるときは、引数の型も指定しないと「あいまいな一致が見つかりました。」としてAmbiguousMatchExceptionが投げられます。

public System.Reflection.MethodInfo GetMethod (
    string name,
    System.Reflection.BindingFlags bindingAttr, // バインディング制約
    System.Reflection.Binder binder,            // プロパティの一式を定義し、バインディングを有効にするオブジェクト
    Type[] types,                               // 引数の数、並び、型を表す
    System.Reflection.ParameterModifier[] modifiers // typesの要素の属性
    );
MethodInfo method1 = type.GetMethod(
    "Method1",
    BindingFlags.NonPublic | BindingFlags.Instance,
    null,
    new[] { typeof(int), typeof(int) },
    null);

静的なメソッドを呼び出すならば、GetMethod()のbindingAttrにBindingFlags.Staticを指定します。

public object Invoke (
    object obj,         // メソッドまたはコンストラクタを呼び出すクラスのオブジェクト
    object[] parameters // メソッドまたはコンストラクタへ渡す引数のリスト
    );
Invoke(Object, Object[]) - MethodBase.Invoke メソッド (System.Reflection) | Microsoft Learn

呼び出すのが静的なメソッドならば、objは無視されます。引数がないならばparametersはnullとします。あるならば引数と同数の長さの配列を渡さないと、「パラメーター カウントが一致しません。」としてTargetParameterCountExceptionが投げられます。

メソッドの引数にrefやoutなどのパラメータ修飾子が付けられているならば、parametersに渡す引数をローカルで保持しておきます。c# - How to pass a parameter as a reference with MethodInfo.Invoke - Stack Overflow

int a = 1;
object[] parameters = new object[] { a };

method1.Invoke(obj, parameters);
// 値をコピーして渡しているためaには作用しないが、parameters[0]から結果を得られる

このように呼び出したメソッドからはすべての例外がTargetInvocationExceptionで投げられるため、実際の例外はそれのInnerExceptionで確認します。TargetInvocationException クラス (System.Reflection) | Microsoft Learn

MakeGenericMethod()

ジェネリック メソッドの定義に置き換えたMethodInfoを得ることで、それを呼び出せます。MethodInfo.MakeGenericMethod(Type[]) Method (System.Reflection) | Microsoft Learn

たとえばメソッドが、

public class MyClass
{
    public void Method<T>(T val) {}
}

のように定義されているならば、次のように呼び出せます。

Type type = typeof(MyClass);
MethodInfo method = type.GetMethod("Method");

MyClass obj = new MyClass();
// method.Invoke(obj, new object[] { 1 }); // InvalidOperationException「ContainsGenericParameters が true に設定されている型またはメソッド上で遅延バインディング操作を実行することはできません。」

// obj.Method<int>(1); の呼び出し
MethodInfo genericMethod1 = method.MakeGenericMethod(typeof(int));
genericMethod1.Invoke(obj, new object[] { 1 });

// obj.Method<string>("a"); の呼び出し
MethodInfo genericMethod2 = method.MakeGenericMethod(typeof(string));
genericMethod2.Invoke(obj, new object[] { "a" });
Microsoft Learnから検索