Funcで実行される呼び出されたメソッドの名前を取得する
-
22-07-2019 - |
質問
Funcとして委任されているメソッドの名前を取得したい。
Func<MyObject, object> func = x => x.DoSomeMethod();
string name = ExtractMethodName(func); // should equal "DoSomeMethod"
どうすればこれを達成できますか?
-自慢する権利について-
Make ExtractMethodName
はプロパティ呼び出しでも機能し、そのインスタンスのプロパティ名を返します。
eg。
Func<MyObject, object> func = x => x.Property;
string name = ExtractMethodName(func); // should equal "Property"
解決
馬を見て!式ツリーはありません!
これは、基になるラムダのILストリームからメタデータトークンを取得して解決する、迅速でダーティな実装固有のバージョンです。
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;
}
他のヒント
これは一般的なケースでは不可能だと思います。持っていた場合:
Func<MyObject, object> func = x => x.DoSomeMethod(x.DoSomeOtherMethod());
何を期待しますか?
とはいえ、リフレクションを使用してFuncオブジェクトを開き、内部で何が行われるかを確認できますが、特定の場合にのみ解決できます。
ハックの答えをここでチェックしてください:
「fieldof」がない理由C#の `または` methodof`演算子?
過去には、Func
の代わりにExpression<Func<...>>
を使用する別の方法を使用しましたが、結果にはあまり満足していませんでした。 MemberExpression
メソッドでフィールドを検出するために使用されるfieldof
は、プロパティが使用されるとPropertyInfo
を返します。
編集#1:これは問題のサブセットに対して機能します:
Func<object> func = x.DoSomething;
string name = func.Method.Name;
編集#2:ここで何が起こっているのかを理解するために、私をマークダウンした人は少し時間をとるべきです。式ツリーは、ラムダ式で暗黙的に使用でき、ここで特定の要求された情報を取得するための最も速く、最も信頼できる方法です。
所属していません StackOverflow