- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
出于测试目的,我正在检查引用类中的一系列方法签名是否已在不同的静态类上实现。对于他们中的大多数人来说,以下是有效的:
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/
我是一名优秀的程序员,十分优秀!