开发者

If I have a MethodInfo on a closed generic Type is there an easy way to switch those types?

Let's say that I have the methodInfo for something like Nullable<int>.HasValue. Is there anyway to convert it to Nullable<string>.HasValue?

I know for a regular generic method I can do methodInfo.GetGenericMethod() but I don't see a way to do it for the type from the method, without doing more reflection overhead. If I already have the method why do I have to reflect again?

Interestingly enough the methods all have the same MetadataToken, which makes it more impressive that somehow Module.ResolveMember seems to pull the right one out.

Is there any way to do this with the Module.ResolveMethod? Essentially, the method and type may both have generic parameters, and I may need to switch them. Since the MethodInfo always says its token is the same and the token represents the MethodInfo is the most open version of the method. I just need someway for it to be converted to my type.

Edit: More digging, it appears that for something like List<T>.Add, List<int>.Add metadata token from which i retrieve is actually living in my module, while the generic definition lives in a different module.

I really don't want to do reflection once I retrieve the member once, as it's very difficult to resolve the exact same method being invoked.

Okay maybe I'm just stupid, but why exactly does this not work::

var methodinfo = typeof(开发者_JS百科List<int>).GetMethod("Add");
var handle = methodinfo.MetaDataToken;
var methodinfo2 = methodinfo.Module.ResolveMethod(handle,new []{typeof(string)},null);

Why does methodInfo2 say that it is Add(T) rather than Add(string)?


You can do it in one line with MethodBase.GetMethodFromHandle but in order to use this method you'll have to pass typeof(List<string>) not just 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);

This link includes the above sample and an exlpanation of why ResolveMethod doesn't work.

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


You can do it easily with a little more reflection. You can't do it magically without reflection.

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

Of course this is pretty specific to only work for generic types with a single type parameter but it could be generalized to do more if needed.


You have to reflect again because the methods are different. While the only difference for HasValue is the MethodInfo.DeclaringType, the difference in the Value property is the MethodInfo.ReturnType.


Solved it. But the big question is this a safe way to do it? Is there something I could be doing wrong here?

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜