C# 如果我有一个关于封闭泛型类型的MethodInfo,有没有一个简单的方法来切换这些类型?

C# 如果我有一个关于封闭泛型类型的MethodInfo,有没有一个简单的方法来切换这些类型?,c#,reflection,C#,Reflection,假设我有类似Nullable.HasValue的methodInfo。 是否仍要将其转换为可为null的.HasValue 我知道对于常规泛型方法,我可以执行methodInfo.GetGenericMethod(),但我看不到一种方法可以在不执行更多反射开销的情况下,从方法中为类型执行此操作。如果我已经有了方法,为什么还要再反思 有趣的是,所有方法都具有相同的MetadataToken,这使得Module.ResolveMember似乎以某种方式拔出了正确的一个更令人印象深刻 使用模块.Res

假设我有类似
Nullable.HasValue
的methodInfo。 是否仍要将其转换为可为null的.HasValue

我知道对于常规泛型方法,我可以执行
methodInfo.GetGenericMethod()
,但我看不到一种方法可以在不执行更多反射开销的情况下,从方法中为类型执行此操作。如果我已经有了方法,为什么还要再反思

有趣的是,所有方法都具有相同的
MetadataToken
,这使得Module.ResolveMember似乎以某种方式拔出了正确的一个更令人印象深刻

使用
模块.ResolveMethod
有什么方法可以做到这一点吗?本质上,方法和类型可能都有泛型参数,我可能需要切换它们。因为MethodInfo总是说它的令牌是相同的,并且令牌表示MethodInfo是该方法最开放的版本。我只需要想办法把它转换成我喜欢的类型

编辑: 更深入的挖掘,似乎对于类似
List.Add
List.Add
这样的东西,我从中检索的元数据标记实际上存在于我的模块中,而通用定义存在于不同的模块中

我真的不想在检索一次成员后进行反射,因为很难解析所调用的完全相同的方法

好吧,也许我很愚蠢,但为什么这不起作用呢

var methodinfo = typeof(List<int>).GetMethod("Add");
var handle = methodinfo.MetaDataToken;
var methodinfo2 = methodinfo.Module.ResolveMethod(handle,new []{typeof(string)},null);
var methodinfo=typeof(List).GetMethod(“Add”);
var handle=methodinfo.MetaDataToken;
var methodinfo2=methodinfo.Module.ResolveMethod(句柄,新[]{typeof(string)},null);

为什么methodInfo2说它是
Add(T)
,而不是
Add(string)

你只需稍微反省一下就可以轻松地完成。你不可能不经过思考就神奇地做到这一点

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

当然,这非常具体,仅适用于具有单个类型参数的泛型类型,但如果需要,可以将其推广以执行更多操作。

由于方法不同,您必须再次进行反思。HasValue的唯一区别是MethodInfo.DeclaringType,而Value属性的区别是MethodInfo.ReturnType

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

    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();
    }
公共静态MethodInfo转换(此MethodInfo方法,参数类型[]DeclaringTypeArguments)
{
var baseType=method.DeclaringType.GetGenericTypeDefinition().MakeGenericType(DeclaringTypeArguments);
返回MethodInfo.GetMethodFromHandle(method.MethodHandle,baseType.TypeHandle)作为MethodInfo;
}
公共静态void Main(字符串[]args)
{
列表=新列表();
Action=list.Add;
Console.WriteLine(action.Method.Convert(typeof(string)));
Console.Read();
}

您可以使用
MethodBase.GetMethodFromHandle
在一行中执行此操作,但要使用此方法,您必须传递
typeof(List)
而不仅仅是
typeof(string)

var methodinfo=typeof(List).GetMethod(“Add”);
var methodinfo2=MethodBase.GetMethodFromHandle(methodinfo.MethodHandle,
typeof(List.TypeHandle);
Console.WriteLine(methodinfo);
Console.WriteLine(methodinfo2);
此链接包括上面的示例和解释
resolvethod
不起作用的原因


此方法还可以为开放泛型类型中的方法获取与封闭泛型类型中的给定方法相对应的
MethodInfo
s。但是请注意,
FieldInfo.GetFieldFromHandle
不是这样工作的,您必须使用
typeof(Generic).GetField(field.Name,…)
var methodinfo = typeof(List<int>).GetMethod("Add");
var methodinfo2 = MethodBase.GetMethodFromHandle(methodinfo.MethodHandle,
                                                 typeof (List<string>).TypeHandle);

Console.WriteLine(methodinfo);
Console.WriteLine(methodinfo2);