Recupero del nome del metodo invocato eseguito in un Func
-
22-07-2019 - |
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"
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.