获取泛型参数类型和价值提供给通用的方法 [英] Get generic argument type and value supplied to a generic method

查看:114
本文介绍了获取泛型参数类型和价值提供给通用的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

How do you get the argument value supplied to a closed/constructed generic method?

这已经有一段时间,因为我还没有触及反思。这一切都曾经是在我的后面,嗯,什么的。

It's been a while since I haven't touched Reflection. All this used to be at the back of my, umm, whatever.

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

This question is absurd and hence closed by the asker. He wishes to retain it just to show his children how stupid daddy was, if they ever turned out to be C# programmers.

推荐答案

简短的回答是typeof运算(Q)。

The short answer is typeof(Q).

长的答案(它试图解释为什么你不能枚举这些类型的,你必须专门编写它们)是这样的:

The long answer (which tries to explain why you can't enumerate these types and you must write them specifically) goes like this:

每个泛型方法(这是更通用比它的声明类)有相应的,不同的MethodInfo的情况下,对所有的(曾经)触及particularizations,另一个的MethodInfo为模板/ open方法。

Each generic method (which is more generic than it's declaring class) has corresponding, distinct MethodInfo instances for all of its (ever) touched particularizations and another MethodInfo for the "template"/open method.

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

You could use this to obtain what you want:

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

     // etc
   }
}

这是为什么? 这是因为没有在反思列举行动返回引用封闭particularizations MethodInfo的实例。

Why is that ? It's because none of the "enumerating operations" in reflection return MethodInfo instances that refer to closed particularizations.

如果您通过枚举声明ConcreteFoo像这样的静态方法:

If you enumerate the static methods declared by ConcreteFoo like so:

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和它的particularizations的陪同人员而言,将只得到与GenericMethod(开放式的变体),相关联的反射对象

you will get identical results. As far as GenericMethod and it's entourage of particularizations are concerned, you will get only the reflection object associated with GenericMethod (open variant).

atTime2将不包含额外的MethodInfo指的是新鲜即时编译GenericMethod&LT;布尔>。

atTime2 will not contain an extra MethodInfo referring to the freshly jitted GenericMethod< bool >.

但是,这不是真的是一件坏事,现在是什么呢? 的getMethods()应该返回一致的结果,而不是有它的效果随时间变化。 通用方法的代数实际上是相当不错的,当涉及到它的导航操作:

But that not's really a bad thing, now is it ? GetMethods() should return consistent results and not have its results vary in time. The algebra of generic methods is actually quite nice when it comes to it's "navigation" operations:

  1. 在所有开放式MethodInfos有IsGenericMethod =真实,IsGenericMethodDefinition = TRUE
  2. 在全封闭MethodInfos有IsGenericMethod =真,IsGenericMethodDefinition = FALSE
  3. 将在一个封闭的MethodInfo你打开一个
  4. 调用.GetGenericMethodDefinition()
  5. 将调用.MakeGenericType(PARAMS键入[]类型)在一个开放的MethodInfo你得到什么闭一只你要(而不语法知道什么这些类型和不尊重的where子句接受一个例外的可能性)
  1. All open MethodInfos have IsGenericMethod = true and IsGenericMethodDefinition = true
  2. All closed MethodInfos have IsGenericMethod = true and IsGenericMethodDefinition = false
  3. By calling .GetGenericMethodDefinition() on a closed MethodInfo you get the open one
  4. By calling .MakeGenericType(params Type[] types) on an open MethodInfo you get whatever closed one you want (without being syntactically aware of what those types are and with the possibility of receiving an exception for not respecting the where clauses)

这同样适用于该来自当前线程的透视图(而不是从所述组件和类型的)的反射操作:

The same goes for the reflection operations that come from the current thread's perspective (rather than from that of the assemblies and types):

MethodBase MethodInfo.GetCurrentMethod()

StackTrace trace = new StackTrace();
IEnumerable<MethodBase> methods = from frame in trace.GetFrames()
                                  select frame.GetMethod();

有去无回的泛型方法的实际关闭的变体(如果有的话) 这实际上是在顶部,或在整个当前调用堆栈。

never return the actual closed variants of generic methods (if any) that are actually on the top, or throughout the current call stack.

在某种程度上你的问题不是荒谬的,因为虽然在的情况下的 GetCurrentMethod 你可以用 GetCurrentMethod 以及 MakeGenericMethod 再加上语法可用的typeof(无论)轻松更换,你不能说你的来电。

In a way your question is not absurd, because, while in the case of GetCurrentMethod you could easily replace it with GetCurrentMethod plus MakeGenericMethod plus the syntactically available typeof(Whatever), you can't say that about your callers.

所以..对于非通用的方法,你可以经常看你的筹码,知道precisely那些是什么方法参数类型。该调用对方,最终你得到调用......但是对于一般的人(这是真正真正关闭的,因为我再说一遍是不合逻辑的思考方法是运行和调用另一个,被称为别人一个通用的方法(等)是一个开放的),你不能找出参数,就像你的类型不能学习任何这样的方法局部变量(其值是确定的,但是这将是一个很大的缺陷在性能上做出一个可能性)。

So.. for non-generic methods you can always look at your stack and know precisely what are those methods' parameter types. The methods that invoked each other and eventually yours got invoked... But for generic ones (which are really truly closed, for I repeat it is illogical to think that a generic method that runs and calls another and was called by someone else (etc) is an open one) you can't find out the types of the parameters just like you can't learn the values of any such methods' local variables (which are deterministic but it would be a great flaw in performance to make that a possibility).

这篇关于获取泛型参数类型和价值提供给通用的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆