Domanda

Vorrei ottenere il nome del metodo che viene delegato come Func.

Func<MyObject, object> func = x => x.DoSomeMethod();
string name = ExtractMethodName(func); // should equal "DoSomeMethod"

Come posso raggiungere questo obiettivo?

- Per vantarsi -

Rendi ExtractMethodName funzionante anche con una chiamata di proprietà, facendola restituire il nome della proprietà in quell'istanza.

ad es.

Func<MyObject, object> func = x => x.Property;
string name = ExtractMethodName(func); // should equal "Property"
È stato utile?

Soluzione

Guarda Ma! Nessun albero di espressione!

Ecco una versione rapida, sporca e specifica per l'implementazione che cattura il token dei metadati dal flusso IL della lambda sottostante e lo risolve.

private static string ExtractMethodName(Func<MyObject, object> func)
{
    var il = func.Method.GetMethodBody().GetILAsByteArray();

    // first byte is ldarg.0
    // second byte is callvirt
    // next four bytes are the MethodDef token
    var mdToken = (il[5] << 24) | (il[4] << 16) | (il[3] << 8) | il[2];
    var innerMethod = func.Method.Module.ResolveMethod(mdToken);

    // Check to see if this is a property getter and grab property if it is...
    if (innerMethod.IsSpecialName && innerMethod.Name.StartsWith("get_"))
    {
        var prop = (from p in innerMethod.DeclaringType.GetProperties()
                    where p.GetGetMethod() == innerMethod
                    select p).FirstOrDefault();
        if (prop != null)
            return prop.Name;
    }

    return innerMethod.Name;
}

Altri suggerimenti

Non penso che ciò sia possibile nel caso generale. E se avessi:

Func<MyObject, object> func = x => x.DoSomeMethod(x.DoSomeOtherMethod());

Cosa ti aspetteresti?

Detto questo, puoi usare la riflessione per aprire l'oggetto Func e vedere cosa fa dentro, ma sarai in grado di risolverlo solo in determinati casi.

Controlla la mia risposta hack qui:

Perché non esiste un campo operatore `o` methodof` in C #?

In passato l'ho fatto in un altro modo utilizzando Func anziché Expression<Func<...>>, ma ero molto meno soddisfatto del risultato. Il MemberExpression utilizzato per rilevare il campo nel mio metodo fieldof restituirà un PropertyInfo quando viene utilizzata una proprietà.

Modifica n. 1: funziona per un sottoinsieme del problema:

Func<object> func = x.DoSomething;
string name = func.Method.Name;

Modifica n. 2: chiunque mi abbia segnato dovrebbe prendere un secondo per capire cosa sta succedendo qui. Gli alberi delle espressioni possono essere implicitamente utilizzati con le espressioni lambda e rappresentano il modo più rapido e affidabile per ottenere le informazioni specifiche richieste qui.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top