C# 获取提供给泛型方法的泛型参数类型和值

C# 获取提供给泛型方法的泛型参数类型和值,c#,.net,reflection,C#,.net,Reflection,如何获得提供给封闭/构造泛型方法的参数值 我已经有一段时间没碰反射了。所有这些过去都是我的,嗯,随便什么 class Program { static void Main(string[] args) { new ConcreteFoo().GenericMethod<int>(5); Console.ReadKey(); } } class ConcreteFoo { public void GenericMetho

如何获得提供给封闭/构造泛型方法的参数值

我已经有一段时间没碰反射了。所有这些过去都是我的,嗯,随便什么

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程序员的话。

简单的答案是typeofQ

一个很长的答案试图解释为什么你不能列举这些类型,你必须写它们,具体如下:

每个泛型方法比它声明的类更泛型,对于它曾经接触过的所有具体化都有相应的、不同的MethodInfo实例,对于模板/打开方法有另一个MethodInfo实例

您可以使用它来获得您想要的:

class ConcreteFoo {    
   public void GenericMethod<Q>(Q q) {
     var method = MethodInfo.GetCurrentMethod();
     var closedMethod = method.MakeGenericMethod(typeof(Q));

     // etc
   }
}
您将得到相同的结果。 就GenericMethod及其具体化环境而言,您将只获得与genericmethodopenvariant关联的反射对象

atTime2将不包含引用新jitted GenericMethod的额外MethodInfo

但这不是一件坏事,是吗? GetMethods应该返回一致的结果,而不是让其结果随时间变化。 泛型方法的代数在其导航操作方面实际上相当不错:

所有打开的方法信息都具有IsGenericMethod=true和IsGenericMethodDefinition=true 所有关闭的方法信息都具有IsGenericMethod=true和IsGenericMethodDefinition=false 通过对关闭的MethodInfo调用.GetGenericMethodDefinition,可以得到打开的MethodInfo 通过在打开的MethodInfo上调用.MakeGenericTypeparams Type[]types,您可以得到所需的任何闭合类型,而不会从语法上知道这些类型是什么,并且可能会收到不遵守where子句的异常 对于来自当前线程的透视图而不是来自程序集和类型的透视图的反射操作也是如此:

MethodBase MethodInfo.GetCurrentMethod()

永远不要返回泛型方法的实际闭合变量(如果有) 实际上位于顶部或整个当前调用堆栈中的

在某种程度上,您的问题并不荒谬,因为在GetCurrentMethod的情况下 您可以很容易地将其替换为GetCurrentMethod加上MakeGenericMethod加上语法上可用的TypeOfWhat,但您不能这样说您的调用者


所以。。对于非泛型方法,您可以随时查看堆栈,精确地知道这些方法的参数类型。相互调用并最终调用您的方法的方法。。。但对于真正封闭的普通类,我再说一遍,认为一个运行并调用另一个、被其他人调用的通用方法是一个开放的方法是不合逻辑的。你无法找到参数的类型,就像你无法了解任何此类方法的局部变量的值一样,这些局部变量是确定性的,但如果将其作为可能性。

您不能使用q.GetType有什么具体原因吗?typeofQ将为您提供当前方法的运行时提供的类型。如果它是您所要求的……只是澄清上面两条注释之间的区别:q.GetType将获得对象的实际类型,这意味着它可以是一个子类,或者如果q是一个接口,则可以是一个实现。typeofQ将返回显式调用方法时使用的泛型类型:GenericMethod1 Q是Object,或隐式调用:GenericMethod1 Q是Int32,而不管传入的类型如何。如果该方法已自行解析,您应该能够将其删除。@ChrisSinclair谢谢,Chris。非常好地解释了运行时类型和编译时类型之间的区别。我刚才看到了这个答案。我不擅长记录我过去问题的答案。非常感谢你如此详尽的回答。我明天就要读了,我可以看到绿色的支票朝你走来-
MethodBase MethodInfo.GetCurrentMethod()
StackTrace trace = new StackTrace();
IEnumerable<MethodBase> methods = from frame in trace.GetFrames()
                                  select frame.GetMethod();