在运行时确定派生类类型

时间:2009-11-18 16:55:34

标签: c# .net generics

我有一个带new()约束的泛型方法。我使用抽象类型调用此方法,当然,它不会编译。我希望保持调用泛型,但希望我可以在运行时确定派生类是什么,以满足编译器。电话会看起来像这样:

var result = MyGenericMethod<FindDerivedClass(myAbstractClass)>();

我尝试过typeof(),但这似乎不起作用。

4 个答案:

答案 0 :(得分:1)

  

我有一个带new()约束的泛型方法。我使用抽象类型调用此方法,当然,它不会编译。我希望保持调用泛型,但希望我能在运行时确定派生类是什么,以满足编译器

这不是编译,而是您需要担心的实际语义。你有一个new()约束的方法 - 这表明该方法需要实例化它传递的T的对象。您希望将抽象类作为T传递 - 但这意味着什么?泛型方法在想要实例化时应该怎么做?

您需要确定这些问题的答案:如果该方法不需要实例化T,为什么它有new()约束?如果它确实需要实例化一个T,那么如果你以某种方式设法使编译器接受一个抽象类T,它应该做什么?

答案 1 :(得分:1)

要在运行时使用泛型,您需要使用反射 - 在程序集中查看所需的所有类型(您可以使用Type.IsSubclassOf),为通用方法获取MethodInfo想要对其进行调用,然后使用MethodInfo.MakeGenericMethod替换为您要调用的实际类型,并使用Invoke

进行调用

答案 2 :(得分:0)

糟糕的想法,您想要采用DerivedClass吗?如果有多个怎么办?如果没有DerivedClass会怎么样?

您可以将类型作为类类型参数传递,而不是方法类型参数:

abstract class MyAbstractClass<T> where T : MyAbstractClass<T>, new()
{
  T MyMethod() { return new T(); }
}

答案 3 :(得分:0)

如果MyGenericMethod是实例方法:

var method = typeof(this).GetMethod("MyGenericMethod", Type.EmptyTypes);
method = method.MakeGenericMethod(new Type[] { FindDerivedClass(myAbstractClass) });
Action action = (Action)Delegate.CreateDelegate(typeof(Action), this, method);
action();

如果MyGenericMethod是静态方法:

var method = typeof(TypeWithGenericMethod).GetMethod("MyGenericMethod", BindingFlags.Public | BindingFlags.Static, null, Type.EmptyTypes, null);
method = method.MakeGenericMethod(new Type[] { FindDerivedClass(myAbstractClass) });
Action action = (Action)Delegate.CreateDelegate(typeof(Action), method);
action();

如果MyGenericMethod返回值,则使用Func<ReturnType>代替Action代理。