代码之家  ›  专栏  ›  技术社区  ›  Michael B

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

  •  7
  • Michael B  · 技术社区  · 15 年前

    比如说,我有一个关于 Nullable<int>.HasValue . 还有什么可以转换成的吗 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);
    

    为什么卫理公会说 Add(T) 而不是 Add(string) ?

    4 回复  |  直到 12 年前
        1
  •  10
  •   Samuel Neff    15 年前

    你可以用一行字 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

        2
  •  2
  •   Samuel Neff    15 年前

    你可以更仔细地思考一下。你不能不经思考就神奇地完成它。

        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);
        }
    

    当然,这只适用于具有单个类型参数的泛型类型,但如果需要,可以将其概括为执行更多操作。

        3
  •  0
  •   Iain    15 年前

    你必须重新思考,因为方法是不同的。虽然hasValue的唯一区别是MethodInfo.DeclaringType,但Value属性中的区别是MethodInfo.ReturnType。

        4
  •  0
  •   Michael B    15 年前

    解决了它。但最大的问题是这是一种安全的方法吗?这里有什么我可能做错的地方吗?

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