使用Type对象创建泛型

7
我正在尝试使用Type对象创建一个泛型类的实例。
基本上,我将在运行时拥有一个不同类型的对象集合,由于无法确定它们确切的类型,因此我认为必须使用反射。
我正在处理类似以下内容的东西:
Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
object obj = Activator.CreateInstance(genType);

这是很好的。 ^___^

问题在于,我想访问我的GenericType<>实例的一个方法,但我无法访问它,因为它被定义为对象类。我无法找到一种将obj转换为特定的GenericType<>的方法,因为这本身就是问题(即,我不能像下面这样输入内容:)

((GenericType<elType>)obj).MyMethod();

如何解决这个问题?

非常感谢!^___^


我在这里发布了一些示例代码,展示了我如何解决这个问题。链接 - Xavier Guzman
7个回答

5
您需要继续使用反射来调用实际方法:
// Your code
Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
object obj = Activator.CreateInstance(genType);

// To execute the method
MethodInfo method = genType.GetMethod("MyMethod",
    BindingFlags.Instance | BindingFlags.Public);
method.Invoke(obj, null);

更多信息请参见Type.GetMethodMethodBase.Invoke


@Richard Neil Ilagan:嗯...有一些运气。下个月(大约)微软将发布VS 2010和.NET 4。当这发生时,您将能够完全按照您在问题中编写的内容进行操作;我在答案中提到的“dynamic”关键字将在运行时绑定到方法,而不是编译时(这意味着如果该方法不存在,您将在运行时获得异常,而不是编译器错误)。您现在可以免费使用VS2010的发行候选版来尝试.NET 4。 - Randolpho
也许你会对Fasterflect(http://fasterflect.codeplex.com)感兴趣。它是一个旨在通过代码生成使反射更易于使用和更快的库。它可以让你做一些很酷的事情,比如在给定一组参数的情况下调用最佳重载匹配,以及更基本的东西。 - Morten Mertner
@Randolpho ~ 是的!我对.NET4的这个方面也有点兴奋。希望我们能够从一开始就成功地迁移我们的应用程序!@Morten ~ 非常感谢!这肯定会让我的辅助代码库更加完善。 :) - Richard Neil Ilagan

4

一旦开始反射游戏,就必须玩到结束。由于类型在编译时不知道,因此无法进行强制转换。您将需要通过反射调用方法:

obj.GetType().InvokeMember(
    "MyMethod", 
    BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod, 
    null, 
    obj, 
    null
);

2
+1。喜欢那第一行。兄弟,你得玩到最后。 编辑我刚刚输了游戏。 - Randolpho

3

2
最直接的方法是从GenericType中提取一个非通用超类型(基类或接口),其中包含您想要为此目的公开的方法:
class GenericType<T> : GenericBase { ... }
class GenericBase { abstract void MyMethod(); }

如果无法做到这一点,可以像@Aaronaught建议的那样使用反射来访问方法本身。

1
创建实例后,只需执行以下操作:
MethodInfo method = genType.GetMethod("MyMethod");
method.Invoke(obj, null);

0

我不确定你的类型有多少变化,或者你是否控制将在其中调用的方法,但创建一个定义要调用哪个函数集的接口可能会很有用。因此,在创建实例后,您可以将其转换为接口并调用所需的任何函数。

因此,请创建您的标准接口(如果您对它们有控制权,则需要在每种类型中实现):

interface IMyInterface
{
   void A();
   int  B();
}

class One : IMyInterface
{
   ...
   implement A and B
   ...
}

Type elType = Type.GetType(obj);
Type genType = typeof(GenericType<>).MakeGenericType(elType);
IMyInterface obj = (IMyInterface)Activator.CreateInstance(genType);
obj.A();

0
如果您知道要调用的方法的签名,您不仅可以像其他示例中所示那样使用MethodInfo.Invoke(),而且还可以创建一个委托,这允许更高效的调用(如果您需要多次调用同一方法),使用Delegate.CreateDelegate()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接