Récupérer le nom de la méthode invoquée exécutée dans un Func
-
22-07-2019 - |
Question
J'aimerais connaître le nom de la méthode déléguée en tant que Func.
Func<MyObject, object> func = x => x.DoSomeMethod();
string name = ExtractMethodName(func); // should equal "DoSomeMethod"
Comment puis-je y parvenir?
- Pour se vanter -
Assurez-vous que ExtractMethodName
fonctionne également avec un appel de propriété, en renvoyant le nom de la propriété dans cette instance.
par exemple.
Func<MyObject, object> func = x => x.Property;
string name = ExtractMethodName(func); // should equal "Property"
La solution
Regarde maman! Pas d'arbres d'expression!
Voici une version rapide, incorrecte et spécifique à l'implémentation qui récupère le jeton de métadonnées du flux IL du lambda sous-jacent et le résout.
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;
}
Autres conseils
Je ne pense pas que cela soit possible dans le cas général. Et si vous aviez:
Func<MyObject, object> func = x => x.DoSomeMethod(x.DoSomeOtherMethod());
Qu'attendriez-vous?
Cela étant dit, vous pouvez utiliser la réflexion pour ouvrir l'objet Func et voir ce qu'il fait à l'intérieur, mais vous ne pourrez le résoudre que dans certains cas.
Découvrez ma réponse hack ici:
Pourquoi n'y a-t-il pas de `champ of Opérateur `ou` methodof` en C #?
Dans le passé, je l’utilisais d’une autre manière qui utilisait Func
au lieu de Expression<Func<...>>
, mais j’étais beaucoup moins satisfait du résultat. Le MemberExpression
utilisé pour détecter le champ dans ma fieldof
méthode renverra un PropertyInfo
lorsqu'une propriété est utilisée.
Éditer # 1: Cela fonctionne pour un sous-ensemble du problème:
Func<object> func = x.DoSomething;
string name = func.Method.Name;
Éditer # 2: Celui qui m'a marqué devrait prendre une seconde pour se rendre compte de ce qui se passe ici. Les arbres d’expression peuvent être utilisés implicitement avec les expressions lambda et constituent le moyen le plus rapide et le plus fiable d’obtenir ici les informations spécifiques demandées.