Genericパラメータのバインド

Genericなクラスに対するリフレクションとか調べていて、ふと疑問が浮かびました。

Type t = typeof(List<int>);
object o = Activator.CreateInstance(t);

ActivatorでListインスタンス化していますが、ジェネリックパラメータをint固定じゃなく、実行時に変えたい場合はどうすればいいのでしょうか?

Type t = typeof(List<>);
object o = Activator.CreateInstance(t);

このように、typeofに型を渡すときにジェネリックパラメータを省略すると、特定の型にバインドされていない型が取得出来るようです。この時のtはListとなっています。さて、この型をインスタンス化すると、どうなるでしょうか。では、早速実験です。

#region Using directives

using System;
using System.Collections.Generic;
using System.Reflection;

#endregion

class Program
{
    static void Main(string args)
    {
        // int型のList<>
        Type t1 = typeof(List<int>);
        Console.WriteLine(t1.Name + " of " + t1.GetGenericArguments()[0].Name);
        // ジェネリック型のList<>
        Type t2 = typeof(List<>);
        Console.WriteLine(t2.Name + " of " + t2.GetGenericArguments()[0].Name);
        // ジェネリックパラメータはintにバインドされているのでインスタンス化出来る
        object o1 = Activator.CreateInstance(t1);
        Console.WriteLine("create instance of " + o1.ToString());

        try
        {
            // ジェネリックパラメータはバインドされていないのでインスタンス化出来ない
            object o2 = Activator.CreateInstance(t2);
            Console.WriteLine("create instance of " + o2.ToString());
        }
        catch (ArgumentException e)
        {
            Console.WriteLine(e.Message);
        }

        try
        {
            // ジェネリックパラメータTをdouble型にバインドする
            Type t3 = t2.BindGenericParameters(new Type { typeof(double) });
            // ジェネリックパラメータはdoubleにバインドされているのでインスタンス化出来る
            object o3 = Activator.CreateInstance(t3);
            Console.WriteLine("create instance of " + o3.ToString());
        }
        catch (ArgumentException e)
        {
            Console.WriteLine(e.Message);
        }
        Console.ReadLine();
    }
}

/* 結果
List`1 of Int32
List`1 of T
create instance of System.Collections.Generic.List`1[System.Int32]
Can not create a type for which Type.ContainsGenericParameters is true.
create instance of System.Collections.Generic.List`1[System.Double]
 */

このようにインスタンス化するには、ジェネリックパラメータを特定の型にバインドさせる必要があります。