gpt4 book ai didi

c# - 泛型方法的 Type.GetMethod()

转载 作者:行者123 更新时间:2023-11-30 16:42:28 25 4
gpt4 key购买 nike

出于测试目的,我正在检查引用类中的一系列方法签名是否已在不同的静态类上实现。对于他们中的大多数人来说,以下是有效的:

private static IEnumerable<Signature> GetMethodSigs(Type type)
{
// Get MethodInfos, filter and project into signatures
var methods = type.GetMethods(
BindingFlags.Public
| BindingFlags.DeclaredOnly
| BindingFlags.Static
| BindingFlags.Instance)
.Where(mi => !mi.Name.StartsWith("get_"))
.Where(mi => !mi.Name.StartsWith("set_"))
.Select(o => new Signature(o.Name, o.ReturnType, o.GetParameters().Select(pi => pi.ParameterType)));

return methods;
}

private static MethodInfo FindMethod(Type type, Signature sig)
{
MethodInfo member = type.GetMethod(
sig.Name,
BindingFlags.Public | BindingFlags.Static,
null,
sig.ParameterTypes.ToArray(),
null);
return member;
}

public struct Signature
{
public string Name;
public Type ReturnType;
public IEnumerable<Type> ParameterTypes;

public Signature(string name, Type returnType, IEnumerable<Type> parameterTypes = null)
{
Name = name;
ReturnType = returnType;
ParameterTypes = parameterTypes;
}
}

这是测试类的一部分,但想象一下以下代码驱动该过程:

foreach(var sig in GetMethodSigs(typeof(ReferenceClass)))
Console.WriteLine(FindMethod(typeof(TestClass), sig)?.ToString());

ReferenceClass 上的以下方法签名正常,但 FindMethod() 未在 TestClass 上找到等效方法(确实存在!) :

public static void SomeMethod<T>(SomeDelegate<T> del)

GetMethods() 为我提供了 del 参数的类型 (SomeDelegate`1),但这显然不是适合的类型在 GetMethod() 中搜索,因为 FindMethod() 对此输入返回 null

知道如何操纵从 GetMethods() 返回的值以使用 GetMethod() 搜索泛型方法(明显的微妙之处在于泛型参数是在委托(delegate)中使用,而不是简单的参数类型)?

(我知道有一个版本的 GetMethod() 只是取一个名字,但由于一些方法名称被重载,我还需要搜索参数类型。)

最佳答案

很长一段时间我没有注意到您正在比较两个不同的类定义:

foreach(var sig in GetMethodSigs(typeof(ReferenceClass)))
Console.WriteLine(FindMethod(typeof(TestClass), sig)?.ToString());

这是值得注意的,因为如果类相同,您的上述代码就可以工作。问题是处理泛型的方式(简要查看 Type 源代码,似乎 Equals 使用了引用比较,但是 == 被卸载了我认为编译器。关键是,不同的泛型方法类型不是引用等效的。但验证实际发生的事情留给读者作为练习)。

快速演示(您可以在交互式 shell 中运行它)

public class D { public static void Method<T>(Action<T> t) { } }
(new D()).GetType().GetMethod("Method").GetParameters()[0].ParameterType == (typeof(Action<>))

输出:

false  

但是,如果您检查类型,两者看起来是一样的:

> (new D()).GetType().GetMethod("Method").GetParameters()[0].ParameterType.ToString()
"System.Action`1[T]"
> (typeof(Action<>)).ToString()
"System.Action`1[T]"

好了,问题演示到此为止。您应该能够通过更改 GetMethodSigs 中的选择语句以在每个参数类型上调用 GetGenericTypeDefinition() 来解决此问题:

.Select(o => new Signature(o.Name, o.ReturnType, o.GetParameters().Select(pi => pi.ParameterType.GetGenericTypeDefinition())));  

您现在可以看到以下显示相等:

> (new D()).GetType().GetMethod("Method").GetParameters()[0].ParameterType.GetGenericTypeDefinition() == (typeof(Action<>)).GetGenericTypeDefinition()
true

当然,这只是针对泛型类型。您必须添加一些逻辑以仅在上述 select 语句中适本地调用 .GetGenericTypeDefinition()

更多来自 https://stackoverflow.com/a/1855248/1462295


编辑:

使用 https://stackoverflow.com/a/7182379/1462295 中的代码

(注意上面的空类T)

public class D
{
public static void Method<TT>(Action<TT> t) { }
public static void Method<TT>(TT t) { }
}

public class RefD
{
public static void Method<TT>(Action<TT> t) { }
public static void Method<TT>(TT t) { }
}

foreach(var sig in GetMethodSigs(typeof(RefD)))
Console.WriteLine(GetMethodExt(typeof(D), sig.Name, sig.ParameterTypes.ToArray())?.ToString());

输出

Void Method[TT](System.Action`1[TT])
Void Method[TT](TT)

关于c# - 泛型方法的 Type.GetMethod(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46691470/

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