动态回归内部阶级?

时间:2014-08-28 21:49:27

标签: c# .net reflection

在以下代码中。函数getInstance动态创建AaaBbbCcc的实例。但是,如何动态生成Union3<...>.Case2(Bbb)

Union3<Aaa, Bbb, Ccc> getInstance(int i)
{
    Type t = getType(i); // one of Aaa, Bbb, Ccc
    var instance = Activator.CreateInstance(t);
    // .... set property values
    return ???? // Union3<Aaa, Bbb, Ccc>.Case?(instance) // 1 to 3 to replace the "?"
}

public abstract class Union3<A, B, C>
{
    public abstract T Match<T>(Func<A, T> f, Func<B, T> g, Func<C, T> h);

    public sealed class Case1 : Union3<A, B, C>
    {
        public readonly A Item;
        public Case1(A item) : base() { this.Item = item; }
        public override T Match<T>(Func<A, T> f, Func<B, T> g, Func<C, T> h)
        {
            return f(Item);
        }
    }

    public sealed class Case2 : Union3<A, B, C>
    {
        public readonly B Item;
        public Case2(B item) { this.Item = item; }
        public override T Match<T>(Func<A, T> f, Func<B, T> g, Func<C, T> h)
        {
            return g(Item);
        }
    }

    public sealed class Case3 : Union3<A, B, C>
    {
        public readonly C Item;
        public Case3(C item) { this.Item = item; }
        public override T Match<T>(Func<A, T> f, Func<B, T> g, Func<C, T> h)
        {
            return h(Item);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

动态创建泛型类型时必须使用Type.MakeGenericType

Union3<Aaa, Bbb, Ccc> getInstance<Aaa, Bbb, Ccc>(int i)
{
    Type t = typeof(Aaa); // implementation of getType(i) left out
    var instance = Activator.CreateInstance(t);

    Type unionType = typeof(Union3<,,>).MakeGenericType(typeof(Aaa), typeof(Bbb), typeof(Ccc));
    var nestedTypes = unionType.GetNestedTypes();

    object unionInstance = null;
    Type toCreate = null;

    if (t == typeof(Aaa))
        toCreate= nestedTypes.Single(x => x.Name == "Case1").MakeGenericType(typeof(Aaa), typeof(Bbb), typeof(Ccc));
    else if (t == typeof(Bbb))
        toCreate= nestedTypes.Single(x => x.Name == "Case2").MakeGenericType(typeof(Aaa), typeof(Bbb), typeof(Ccc));
    else if (t == typeof(Ccc))
        toCreate= nestedTypes.Single(x => x.Name == "Case3").MakeGenericType(typeof(Aaa), typeof(Bbb), typeof(Ccc));
    else
        throw new NotImplementedException();

    unionInstance = Activator.CreateInstance(toCreate, instance);
    return (Union3<Aaa, Bbb, Ccc>)unionInstance;
}

最终结果将是具有正确Item Type的3个内部类之一的实例。