调用泛型方法的类型数组

3

我有一个带有以下签名的通用方法:

Broker.GetMessages<TType>();

它可以以下列方式使用:
IList<IEmailMessage> emails = Broker.GetMessages<IEmailMessage>();

我需要对一个包含多种类型的结构体数组中的每一种类型都执行这个方法:
var messageTypes = new [] { typeof(IEmailMessage), typeof(IFaxMessage) }

我的最终结果应该是这样的:

foreach ( IMessage message in messageTypes)
{
   Broker.GetMessages<xxx>();
}

问题在于我不知道如何转换Type以便将其作为泛型参数传递。我知道可以使用反射来调用方法,但我想知道是否有更好的方法来完成这个任务。我可以改变数组结构,但无法改变方法签名。

你最后的代码语句实际上是foreach(Type message in messageTypes)。无论如何,针对你想要做的这件事,我不会选择一个通用方法,而是选择一个普通方法,其输入参数为(Type messageType)。 - Matthias
这个方法的签名应该更像是 Broker.GetMessages(Type messageType);。我敢打赌你在那个方法里调用了 typeof(TType),这表明它根本不应该是泛型的。 - vgru
你完全没有读帖子。我无法更改经纪人的签名,因为它是第三方程序集... - Raffaeu
1个回答

5
不,你需要使用反射。鉴于你已经有了一个Type[]数组,任何时候使用typeof都会使你走上反射的道路,你已经完成了一半。泛型适用于在编译时知道类型的情况,虽然你已经将这些类型硬编码到了messageTypes数组中,但是你仍然断开了在方法调用时和编译时知道类型的联系。
这样做相当简单:
var definition = typeof(Broker).GetMethod("GetMessages");
var generic = definition.MakeGenericMethod(type);
var result = generic.Invoke(null);

我认为调用makeGenericMethod很昂贵,因为它使用了反射。如果不是这样,那么我将采用这种方式使其工作。 - Raffaeu
1
@Raffaeu:我不知道它有多昂贵,但你应该先获得可行的代码,然后再检查成本。如果你真的想要,你可以按类型缓存MakeGenericMethod的结果,但在获得数据表明需要它之前,我不会增加这种复杂性。 - Jon Skeet
谢谢建议,我会尝试让我的测试运行起来,然后再看看它有多昂贵。 - Raffaeu

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