使用反射查找泛型方法时发现歧义匹配

时间:2018-10-24 09:23:14

标签: c# generics reflection generic-method

我正在使用反射来找到Newtonsoft self.navigationController?.pushViewController(displayVC, animated: false) 的通用方法,但是发现它返回的是非通用版本JsonConvert.DeserializedObject<T>的模糊匹配,这是试图获取通用方法:

JsonConvert.DeserializeObject

我已指定我想要一个以return typeof(JsonConvert).GetMethod("DeserializeObject", new Type[] { typeof(string) }).MakeGenericMethod(genericType); 作为其唯一参数的方法,但是通用和非通用版本都具有匹配的参数列表,并且我收到模棱两可的匹配错误。

是否可以通过string来获得通用版本?我知道我可以使用Linq和GetMethod来找到它,例如:

GetMethods()

但这有点麻烦,必须有更好的方法。

4 个答案:

答案 0 :(得分: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
}

用法:

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

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

public static object DeserializeObject(string value)
public static T DeserializeObject<T>(string value)

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

答案 1 :(得分:1)

问题在于Type.GetMethod不允许您指定通用类型,这意味着该代码:

var method = typeof(JsonConvert).GetMethod("DeserializeObject", new[] { typeof(string)})

试图在两种匹配方法JsonConvert.DeserializeObject(string)JsonConvert.DeserializeObject<T>(string)之间进行解析。

不幸的是,您受限于Linq选项来执行此操作。

答案 2 :(得分:0)

我想你想要这个:

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

答案 3 :(得分:0)

GetMethod 方法可以区分泛型和非泛型方法;一个例子是带有整数参数 genericParamCountthis one

<块引用>

搜索参数与指定泛型参数计数和参数类型匹配的指定公共方法。

以下代码:

var genericMethod = typeof(JsonConvert)
    .GetMethod("DeserializeObject", 1, new Type[] { typeof(string) })
    .MakeGenericMethod(typeof(string));
var otherMethod = typeof(JsonConvert)
    .GetMethod("DeserializeObject", 0, new Type[] { typeof(string) });
Console.WriteLine(genericMethod);
Console.WriteLine(otherMethod);

将打印

System.String DeserializeObject[String](System.String)
System.Object DeserializeObject(System.String)

所以这可能是解决您问题的最短方法。