使用反射查找泛型方法时发现不明确的匹配

DGi*_*bbs 6 c# generics reflection generic-method

我正在使用反射来查找 Newtonsoft 的泛型方法,JsonConvert.DeserializedObject<T>但我发现它返回了非泛型版本的不明确匹配JsonConvert.DeserializeObject,这是尝试获取泛型方法的代码:

return typeof(JsonConvert).GetMethod("DeserializeObject", new Type[] { typeof(string) }).MakeGenericMethod(genericType);
Run Code Online (Sandbox Code Playgroud)

我已经指定我想要将 astring作为其唯一参数的方法,但泛型和非泛型版本都有匹配的参数列表,并且我收到了不明确的匹配错误。

是否可以通过GetMethod这种方式获得通用版本?我知道我可以使用 Linq 并GetMethods()找到它,例如:

var method = typeof(JsonConvert).GetMethods().FirstOrDefault(
            x => x.Name.Equals("DeserializeObject", StringComparison.OrdinalIgnoreCase) &&
            x.IsGenericMethod && x.GetParameters().Length == 1 &&
            x.GetParameters()[0].ParameterType == typeof(string));
Run Code Online (Sandbox Code Playgroud)

但这有点麻烦,一定有更好的方法。

Spi*_*ixy 5

我想你想要这个:

var method = typeof(JsonConvert).GetMethods().FirstOrDefault(
    x => x.Name.Equals("DeserializeObject", StringComparison.OrdinalIgnoreCase) &&
    x.IsGenericMethod && x.GetParameters().Length == 1)
    ?.MakeGenericMethod(genericType);
Run Code Online (Sandbox Code Playgroud)


Ale*_*eev 3

你可以从Binder类中派生

class MyBinder : Binder
{
    public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
    {          
        return match.First(m => m.IsGenericMethod);
    }

    #region not implemented
    public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state) => throw new NotImplementedException();
    public override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo[] match, object value, CultureInfo culture) => throw new NotImplementedException();
    public override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, Type returnType, Type[] indexes, ParameterModifier[] modifiers) => throw new NotImplementedException();
    public override object ChangeType(object value, Type type, CultureInfo culture) => throw new NotImplementedException();
    public override void ReorderArgumentArray(ref object[] args, object state) => throw new NotImplementedException();
    #endregion
}
Run Code Online (Sandbox Code Playgroud)

用法:

var method = typeof(JsonConvert).GetMethod("DeserializeObject",
    BindingFlags.Public | BindingFlags.Static,
    new MyBinder(),
    new[] {typeof(string)},
    null);
Run Code Online (Sandbox Code Playgroud)

在您的情况下MyBinder,将收到两名候选人SelectMethod

public static object DeserializeObject(string value)
public static T DeserializeObject<T>(string value)
Run Code Online (Sandbox Code Playgroud)

上面的代码将选择第一个通用方法