InvokeMember löst ein AmbigousMatchException

In diesem Artikel können Sie das Problem beheben, bei dem eine AmbigousMatchException möglicherweise ausgelöst wird, wenn Sie System.Type.InvokeMember mit der aufrufen DefaultBinder , um die nicht generische Version der Funktion aufzurufen Check .

Original Version des Produkts:   Microsoft .NET Framework 4.5
Ursprüngliche KB-Nummer:   2843607

Problembeschreibung

Angenommen, Sie verfügen über eine Klasse, die eine generische Überladung einer Methode aufweist, wie im folgenden Beispiel dargestellt:

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

Wenn Sie System.Type.InvokeMember mit der aufrufen, DefaultBinder um die nicht generische Version der Funktion aufzurufen Check , AmbigousMatchException wird eine ausgelöst.

Ursache

Wenn eine generische Überladung der Methode vorhanden ist, System.Type.DefaultBinder kann nicht zwischen der generischen und der nicht generischen Version der Funktion unterschieden werden.

Lösung

Erstellen einer benutzerdefinierten Sammelmappe um die nicht generische Überladung der Methode zurückzugeben und im Aufruf zu verwenden InvokeMember , ist eine Beispielimplementierung unten:

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