如果我在一个封闭的泛型类型上有一个MethodInfo,那么有一种简单的方法来切换这些类型吗?

时间:2010-11-05 01:38:48

标签: c# reflection

假设我有类似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)

4 个答案:

答案 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不起作用的说明。

https://www.re-motion.org/blogs/mix/archive/2009/08/12/trying-to-resolve-a-method-in-a-closed-generic-type.aspx

答案 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();
    }