Boost.Bind を C# で作りたい(3)

public static class Boost
{
    public class PlaceHolder
    {
        public PlaceHolder(int v) { Value = v; }
        public int Value;
    }

    public static PlaceHolder _1 = new PlaceHolder(1);
    public static PlaceHolder _2 = new PlaceHolder(2);
    public static PlaceHolder _3 = new PlaceHolder(3);

    public abstract class List
    {
        public abstract object Get(object obj);
        public abstract object Invoke(Delegate f, List l);
    }

    public class List0 : List
    {
        public override object Get(object obj)
        {
            return obj;
        }
        public override object Invoke(Delegate f, List l)
        {
            return f.DynamicInvoke();
        }
    }
    public class List1 : List
    {
        object a1;
        public List1(object a1)
        {
            this.a1 = a1;
        }

        public override object Get(object obj)
        {
            if (obj is PlaceHolder) return a1;
            return obj;
        }
        public override object Invoke(Delegate f, List l)
        {
            return f.DynamicInvoke(l.Get(a1));
        }
    }
    public class List2 : List
    {
        public object a1;
        public object a2;

        public List2(object a1, object a2)
        {
            this.a1 = a1;
            this.a2 = a2;
        }

        public override object Get(object obj)
        {
            PlaceHolder ph = obj as PlaceHolder;
            if (ph == null) return obj;
            switch (ph.Value)
            {
                case 0: return a1;
                case 1: return a2;
            }
            return null;
        }
        public override object Invoke(Delegate f, List l)
        {
            return f.DynamicInvoke(l.Get(a1), l.Get(a2));
        }
    }

    public class Bind_t<R>
    {
        Delegate f;
        List l;

        public Bind_t(Delegate f, List l)
        {
            this.f = f;
            this.l = l;
        }

        public R Invoke()
        {
            return (R)f.DynamicInvoke();
        }
        public R Invoke<T1>(T1 t1)
        {
            return (R)l.Invoke(f, new List1(t1));
        }
        public R Invoke<T1, T2>(T1 t1, T2 t2)
        {
            return (R)l.Invoke(f, new List2(t1, t2));
        }
    }

    public delegate R Function<R>();
    public delegate R Function<R, T1>(T1 t1);
    public delegate R Function<R, T1, T2>(T1 t1, T2 t2);

    public static Bind_t<R> Bind<R>(Function<R> f)
    {
        return new Bind_t<R>(f, null);
    }
    public static Bind_t<R> Bind<R, T1>(Function<R, T1> f, object t1)
    {
        return new Bind_t<R>(f, new List1(t1));
    }
    public static Bind_t<R> Bind<R, T1, T2>(Function<R, T1, T2> f, object t1, object t2)
    {
        return new Bind_t<R>(f, new List2(t1, t2));
    }
}
[STAThread]
static void Main()
{
    Boost.Function<int, int> f = Boost.Bind<int, int, int>(func, 100, Boost._1).Invoke<int>;
    int n = f(10); // 110
    f = Boost.Bind<int, int, int>(func, Boost._1, Boost._1).Invoke<int>;
    n = f(100); // 200
}
static int func(int a, int b)
{
    return a + b;
}

静的に型チェック出来てないし値を返さない関数はダメだし引数の数や型を間違えてもコンパイル通るし Bind の戻り値から Invoke<> でわざわざ関数を持ってきてるし微妙すぎる。
もっといい方法無いかなぁ。