使用仅在执行时已知的类型参数调用泛型方法 [英] Calling generic method with a type argument known only at execution time
问题描述
当然,我的真实代码看起来并不完全像这样.我试着写半伪代码来更清楚我想要做什么.
Of course my real code doesn't look exactly like this. I tried to write semi-pseudo code to make it more clear of whay I wanted to do.
看起来它只是把事情搞砸了.
Looks like it just messed things up instead.
所以,我真正想做的是:
So, what I actually would like to do is this:
Method<Interface1>();
Method<Interface2>();
Method<Interface3>();
...
嗯......我想也许我可以使用反射将它变成一个循环.所以问题是:我该怎么做.我非常对反射有很浅的了解.所以代码示例会很棒.
Well ... I thought that maybe I could turn it into a loop using reflection. So the question is: How how do I do it. I have very shallow knowledge of reflection. So code examples would be great.
场景如下:
public void Method<T>() where T : class
{}
public void AnotherMethod()
{
Assembly assembly = Assembly.GetExecutingAssembly();
var interfaces = from i in assembly.GetTypes()
where i.Namespace == "MyNamespace.Interface" // only interfaces stored here
select i;
foreach(var i in interfaces)
{
Method<i>(); // Get compile error here!
}
原帖:
嗨!
我正在尝试遍历命名空间中的所有接口,并将它们作为参数发送给这样的通用方法:
I'm trying to loop through all interfaces in a namespace and send them as arguments to a generic method like this:
public void Method<T>() where T : class
{}
public void AnotherMethod()
{
Assembly assembly = Assembly.GetExecutingAssembly();
var interfaces = from i in assembly.GetTypes()
where i.Namespace == "MyNamespace.Interface" // only interfaces stored here
select i;
foreach(var interface in interfaces)
{
Method<interface>(); // Get compile error here!
}
}
我得到的错误是需要类型名称,但找到局部变量名称".如果我尝试
The error I get is "Type name expected, but local variable name found". If I try
...
foreach(var interface in interfaces)
{
Method<interface.MakeGenericType()>(); // Still get compile error here!
}
}
我得到无法应用运算符‘<’到方法组"和System.Type"类型的操作数"关于如何解决这个问题的任何想法?
I get "Cannot apply operator '<' to operands of type 'method group' and 'System.Type'" Any idea on how to get around this problem?
推荐答案
好的,是时候编写一个简短但完整的程序了.基本答案和以前一样:
Okay, time for a short but complete program. The basic answer is as before:
- 使用 Type.GetMethod 查找打开"泛型方法
- 使用 MakeGenericMethod 使其通用
- 使用 Invoke 调用它
这是一些示例代码.请注意,我将查询表达式更改为点表示法 - 当您基本上只有一个 where 子句时,使用查询表达式是没有意义的.
Here's some sample code. Note that I changed the query expression to dot notation - there's no point in using a query expression when you've basically just got a where clause.
using System;
using System.Linq;
using System.Reflection;
namespace Interfaces
{
interface IFoo {}
interface IBar {}
interface IBaz {}
}
public class Test
{
public static void CallMe<T>()
{
Console.WriteLine("typeof(T): {0}", typeof(T));
}
static void Main()
{
MethodInfo method = typeof(Test).GetMethod("CallMe");
var types = typeof(Test).Assembly.GetTypes()
.Where(t => t.Namespace == "Interfaces");
foreach (Type type in types)
{
MethodInfo genericMethod = method.MakeGenericMethod(type);
genericMethod.Invoke(null, null); // No target, no arguments
}
}
}
原答案
让我们先抛开调用变量接口"的明显问题.
Let's leave aside the obvious problems of calling a variable "interface" to start with.
你必须通过反射来调用它.泛型的重点是在编译时进行更多的类型检查.您在编译时不知道类型是什么 - 因此您必须使用泛型.
You have to call it by reflection. The point of generics is to put more type checking at compile time. You don't know what the type is at compile-time - therefore you've got to use generics.
获取泛型方法,并对其调用 MakeGenericMethod,然后调用它.
Get the generic method, and call MakeGenericMethod on it, then invoke it.
您的接口类型本身实际上是通用的吗?我问是因为你正在调用 MakeGenericType ,但没有传入任何类型参数......你是否试图调用
Is your interface type itself actually generic? I ask because you're calling MakeGenericType on it, but not passing in any type arguments... Are you trying to call
Method<MyNamespace.Interface<string>>(); // (Or whatever instead of string)
或
Method<MyNamespace.Interface>();
如果是后者,您只需要调用 MakeGenericMethod - 而不是 MakeGenericType.
If it's the latter, you only need a call to MakeGenericMethod - not MakeGenericType.
这篇关于使用仅在执行时已知的类型参数调用泛型方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!