gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 17:50:54 24 4
gpt4 key购买 nike

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

我已经有一段时间没有接触反射了。所有这些过去都在我的背后,嗯,无论如何。

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 */ }
}

更新

这个问题很荒谬,因此被提问者关闭了。他希望保留它只是为了向他的 children 展示爸爸是多么愚蠢,如果他们最终成为 C# 程序员的话。

最佳答案

简短的回答是 typeof(Q)。

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

每个通用方法(比它声明的类更通用)都有对应的、不同的 MethodInfo 实例用于其所有(曾经)接触的具体化和另一个 MethodInfo 用于"template"/打开方法。

你可以用它来获得你想要的东西:

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 将不包含引用新生成的 GenericMethod 的额外 MethodInfo。

但这并不是一件坏事,现在是吗?GetMethods() 应该返回一致的结果并且其结果不会随时间变化。当涉及到“导航”操作时,泛型方法的代数实际上非常好:

  1. 所有打开的 MethodInfos 都有 IsGenericMethod = true 和 IsGenericMethodDefinition = true
  2. 所有关闭的 MethodInfo 都具有 IsGenericMethod = true 和 IsGenericMethodDefinition = false
  3. 通过在关闭的 MethodInfo 上调用 .GetGenericMethodDefinition(),您可以获得打开的 MethodInfo
  4. 通过在打开的 MethodInfo 上调用 .MakeGenericType(params Type[] types),您可以得到任何您想要的封闭的(在语法上不知道这些类型是什么,并且有可能因不遵守 where 子句而收到异常)

从当前线程的角度(而不是来自程序集和类型的角度)的反射操作也是如此:

MethodBase MethodInfo.GetCurrentMethod()

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

从不返回泛型方法的实际封闭变体(如果有的话)实际上在顶部,或者在整个当前调用堆栈中。

在某种程度上,您的问题并不荒谬,因为在 GetCurrentMethod 的情况下您可以轻松地将其替换为 GetCurrentMethod 加上 MakeGenericMethod 以及语法上可用的 typeof(Whatever),您不能对调用者这样说。

所以.. 对于非泛型方法,您始终可以查看堆栈并准确了解这些方法的参数类型。相互调用并最终调用您的方法的方法...但是对于通用方法(它们确实是真正关闭的,因为我重复一遍,认为运行并调用另一个并被其他人调用的通用方法是不合逻辑的(等) 是一个开放的)你无法找出参数的类型,就像你无法了解任何此类方法的局部变量的值一样(这是确定性的,但它会是一个很大的性能缺陷)可能性)。

关于c# - 获取提供给泛型方法的泛型参数类型和值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14707298/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com