假设我有类似Nullable<int>.HasValue
之类的methodInfo。
无论如何将它转换为Nullable<string>.HasValue
?
我知道一个常规的泛型方法我可以做methodInfo.GetGenericMethod()
但是我没有看到方法为方法中的类型做这个,而没有做更多的反射开销。如果我已经有了这个方法,为什么我必须再次反思?
有趣的是,这些方法都具有相同的MetadataToken
,这使得更令人印象深刻的是,不知何故,Module.ResolveMember似乎正在推出正确的方法。
有没有办法用Module.ResolveMethod
做到这一点?本质上,方法和类型可能都有通用参数,我可能需要切换它们。由于MethodInfo始终表示其令牌相同且令牌表示MethodInfo是该方法的最开放版本。我只需要将它转换为我的类型。
编辑:
更多的挖掘,似乎对于像List<T>.Add
这样的东西,我检索的List<int>.Add
元数据标记实际上存在于我的模块中,而通用定义存在于不同的模块中。
一旦我检索成员,我真的不想做反射,因为很难解决被调用的完全相同的方法。
好吧也许我只是愚蠢,但为什么这不起作用::
var methodinfo = typeof(List<int>).GetMethod("Add");
var handle = methodinfo.MetaDataToken;
var methodinfo2 = methodinfo.Module.ResolveMethod(handle,new []{typeof(string)},null);
为什么methodInfo2说它是Add(T)
而不是Add(string)
?
答案 0 :(得分:10)
您可以使用MethodBase.GetMethodFromHandle
在一行中执行此操作,但为了使用此方法,您必须通过typeof(List<string>)
而不仅仅是typeof(string)
。
var methodinfo = typeof(List<int>).GetMethod("Add");
var methodinfo2 = MethodBase.GetMethodFromHandle(methodinfo.MethodHandle,
typeof (List<string>).TypeHandle);
Console.WriteLine(methodinfo);
Console.WriteLine(methodinfo2);
此链接包含上述示例以及为什么ResolveMethod
不起作用的说明。
答案 1 :(得分:2)
你可以通过多一点反思轻松完成。没有反思,你不能神奇地做到这一点。
static void Main(string[] args)
{
PropertyInfo intHasValue = typeof (int?).GetProperty("HasValue");
PropertyInfo boolHasValue = ChangeGenericType(intHasValue, typeof (bool));
}
public static PropertyInfo ChangeGenericType(PropertyInfo property, Type targetType)
{
Type constructed = property.DeclaringType;
Type generic = constructed.GetGenericTypeDefinition();
Type targetConstructed = generic.MakeGenericType(new[] {targetType});
return targetConstructed.GetProperty(property.Name);
}
当然,这非常具体,只适用于具有单一类型参数的泛型类型,但如果需要,可以将其推广到更多内容。
答案 2 :(得分:0)
你必须再次思考,因为方法不同。虽然HasValue的唯一区别是MethodInfo.DeclaringType,但Value属性的差异是MethodInfo.ReturnType。
答案 3 :(得分:0)
解决了它。但最大的问题是这是一种安全的方法吗?有什么我可能在这里做错了吗?
public static MethodInfo Convert(this MethodInfo method,params Type[] DeclaringTypeArguments)
{
var baseType = method.DeclaringType.GetGenericTypeDefinition().MakeGenericType(DeclaringTypeArguments);
return MethodInfo.GetMethodFromHandle(method.MethodHandle, baseType.TypeHandle) as MethodInfo;
}
public static void Main(String[] args)
{
List<Type> list = new List<Type>();
Action<Type> action = list.Add;
Console.WriteLine(action.Method.Convert(typeof(string)));
Console.Read();
}