InvokeMember génère une AmbigousMatchException

Cet article vous aide à résoudre le problème où une erreur AmbigousMatchException peut être générée lorsque vous appelez System.Type.InvokeMember à l’aide de la DefaultBinder pour appeler la version non générique de la fonction Check .

Version du produit d’origine :   Microsoft .NET Framework 4,5
Numéro de la base de connaissances initiale :   2843607

Symptômes

Supposons que vous avez une classe qui a une surcharge générique d’une méthode, comme illustré dans l’exemple suivant :

class Test
{
    public Boolean Check<T>(String Value)
    {
        return false;
    }
    public Boolean Check(String Value)
    {
        return true;
    }
}

Si vous appelez System.Type.InvokeMember à l’aide de DefaultBinder pour appeler la version non générique de la fonction Check , une AmbigousMatchException est générée.

Cause

S’il existe une surcharge générique de la méthode, le System.Type.DefaultBinder ne peut pas faire la différence entre la version générique et la version non générique de la fonction.

Résolution

Créer un Binder personnalisé pour renvoyer la surcharge non générique de la méthode et l’utiliser dans l' InvokeMember appel, un exemple d’implémentation est ci-dessous :

public class MyBinder : Binder
{
    public MyBinder()
        : base()
    { }

    public override FieldInfo BindToField(
        BindingFlags bindingAttr,
        FieldInfo[] match,
        object value,
        CultureInfo culture
        )
    {
        return System.Type.DefaultBinder.BindToField(bindingAttr, match, value, culture);
    }

    public override MethodBase BindToMethod(
        BindingFlags bindingAttr,
        MethodBase[] match,
        ref object[] args,
        ParameterModifier[] modifiers,
        CultureInfo culture,
        string[] names,
        out object state
        )
    {

        if (match == null)
            throw new ArgumentNullException();

        List<MethodBase> match2 = new List<MethodBase>();

        for (int i = 0; i < match.Length; i++)
        {
            if (!match[i].IsGenericMethod)
            {
                match2.Add(match[i]);
            }
        }

        return System.Type.DefaultBinder.BindToMethod(bindingAttr, match2.ToArray<MethodBase>(), ref args, modifiers, culture, names, out state);
    }
    public override object ChangeType(
        object value,
        Type myChangeType,
        CultureInfo culture
        )
    {

        return System.Type.DefaultBinder.ChangeType(value, myChangeType, culture);
    }
    public override void ReorderArgumentArray(
        ref object[] args,
        object state
        )
    {
        // Return the args that had been reordered by BindToMethod.
        System.Type.DefaultBinder.ReorderArgumentArray(ref args, state);
    }
    public override MethodBase SelectMethod(
        BindingFlags bindingAttr,
        MethodBase[] match,
        Type[] types,
        ParameterModifier[] modifiers
        )
    {
        return System.Type.DefaultBinder.SelectMethod(bindingAttr, match, types, modifiers);
    }
    public override PropertyInfo SelectProperty(
        BindingFlags bindingAttr,
        PropertyInfo[] match,
        Type returnType,
        Type[] indexes,
        ParameterModifier[] modifiers
        )
    {
        return System.Type.DefaultBinder.SelectProperty(bindingAttr, match, returnType, indexes, modifiers);
    }
}