如何获得提供给封闭/构造的泛型方法的参数值?
我已经有一段时间没有触及反射。所有这一切都在我的后面,嗯,无论如何。
class Program
{
static void Main(string[] args)
{
new ConcreteFoo().GenericMethod<int>(5);
Console.ReadKey();
}
}
class ConcreteFoo
{
public void GenericMethod<Q>(Q q)
{
var method = MethodInfo.GetCurrentMethod();
var parameters = method.GetParameters();
if (parameters.Length > 0)
foreach (var p in parameters)
Console.WriteLine("Type: {0}", p.ParameterType);
// That still prints Q as the type.
// I've tried GetGenericArguments as well. No luck.
// I want to know:
// 1) The closed type, i.e. the actual generic argument supplied by the caller; and
// 2) The value of that argument
}
public void GenericMethodWithNoGenericParameters<Q>()
{
// Same here
}
}
class GenericFoo<T>
{
public void NonGenericMethod(T t) { /* And here*/ }
public void GenericMethod<Q>(Q q) { /* And here */ }
}
更新
这个问题很荒谬,因此被提问者关闭了。他希望保留它只是为了向他的孩子们展示愚蠢的爸爸是多么愚蠢,如果他们原来是C#程序员的话。
答案 0 :(得分:8)
简短回答是typeof(Q)。
长答案(试图解释为什么你不能枚举这些类型,你必须专门编写它们)是这样的:
每个泛型方法(比它的声明类更通用)具有相应的,不同的MethodInfo实例,用于所有(曾经)触摸的特殊化,另一个MethodInfo用于“模板”/ open方法。
你可以用它来获得你想要的东西:
class ConcreteFoo {
public void GenericMethod<Q>(Q q) {
var method = MethodInfo.GetCurrentMethod();
var closedMethod = method.MakeGenericMethod(typeof(Q));
// etc
}
}
为什么? 这是因为反射中的“枚举操作”都没有返回引用闭合特殊化的MethodInfo实例。
如果枚举ConcreteFoo声明的静态方法,如下所示:
var atTime1 = typeof(ConcreteFoo).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
ConcreteFoo.GenericMethod( true );
var atTime2 = typeof(ConcreteFoo).GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
你会得到相同的结果。 就GenericMethod及其随行人员而言,您将只获得与GenericMethod(开放变体)相关联的反射对象。
atTime2将不包含一个额外的MethodInfo,引用新近插入的GenericMethod&lt; bool&gt;。
但这不是一件坏事,现在是吗? GetMethods()应返回一致的结果,并且其结果不会随时间变化。 当涉及到它的“导航”操作时,泛型方法的代数实际上非常好:
对于来自当前线程视角的反射操作(而不是来自组件和类型的反射操作)也是如此:
MethodBase MethodInfo.GetCurrentMethod()
和
StackTrace trace = new StackTrace();
IEnumerable<MethodBase> methods = from frame in trace.GetFrames()
select frame.GetMethod();
永远不会返回泛型方法的实际封闭变体(如果有的话) 它实际上位于顶部或整个当前的调用堆栈中。
在某种程度上,你的问题并不荒谬,因为,在 GetCurrentMethod 的情况下 您可以轻松地将其替换为 GetCurrentMethod 加上 MakeGenericMethod 以及语法上可用的 typeof(Whatever),您无法说出您的来电者。< / p>
因此..对于非泛型方法,您可以随时查看堆栈并准确了解这些方法的参数类型。相互调用并最终调用你的方法被调用了...但是对于通用的方法(它们真的是真正关闭的,因为我重复一遍,认为运行并调用另一个并由其他人调用的通用方法是不合逻辑的(等等) )是一个开放的)你无法找到参数的类型,就像你无法学习任何这样的方法的局部变量的值(这是确定性的,但这将是一个很大的性能缺陷,使这个可能性)。