MethodBase Объект асинхронной функции
В моем приложении у меня есть небольшой журнал действий. Там я сохраняю последние несколько вызовов определенных методов в моем приложении, например:
saveLastAction(MethodBase.GetCurrentMethod(), getCurrentStatus(), item, /*loadFresh*/ false);
Это позволяет мне перемещаться и обновлять мои последние действия
public void Refresh(bool loadFresh = true)
{
if (!isInitialized) return;
try
{
lastStatus = getCurrentStatus();
var parameters = lastActionsParameters.Pop();
var method = lastActions.Pop();
//Set the load Fresh parameter to True
parameters[method.GetParameters().First(pi => pi.Name == "loadFresh").Position] = loadFresh;
//Invoke the Method again with the adopted parameters
method.Invoke(this, parameters);
}
catch
{
}
}
Я работал отлично, пока я не изменил один из методов, который вызывает saveLastAction для асинхронного. С того времени MethodBase.GetCurrentMethod()
возвращает только функцию MoveNext, а не фактическую функцию, которую я вызвал.
Есть ли способ добраться до фактического объекта MethodBase вызываемой функции, неважно, во время сохранения или вызова.
С наилучшими пожеланиями lolsharp
3 ответа
Я создал небольшую справочную функцию:
private MethodInfo getMethodBase(object caller, [CallerMemberName]string methodName = "")
{
//Binding Flags to include private functions
return caller.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
}
Непосредственное использование CallerMemberNameAttribute не работало, потому что я также использовал параметр params. В конце концов, очень похож на подход Питерса.
Вы действительно нуждаетесь в MethodBase
объект? Или достаточно просто записать достаточно подробностей, чтобы человек мог понять, какой это был метод?
Если последнее, то это довольно просто: обратите внимание, что метод, который выполняется, на самом деле содержится в сгенерированном компилятором классе, где само имя класса содержит имя метода, переписанного компилятором для генерации этого класса.
Так в вашем saveLastAction()
метод, где, по-видимому, вы входите MethodBase.Name
значение свойства, вы должны сначала проверить MethodBase.DeclaringType.Name
значение, и если это выглядит <SomeMethodName>d_5
(где особенности после закрывающей угловой скобки также могут различаться), вы можете использовать текст в угловых скобках для имени метода вместо MethodBase.Name
стоимость имущества.
Обратите внимание, что только компилятор может генерировать имена классов с этими угловыми скобками, поэтому вам не нужно беспокоиться о получении ложного срабатывания.
В качестве дополнительного бонуса, это позволит вашему журналу регистрации работать с методами итератора.:)
Если вам нужно MethodBase
Сам объект, это немного сложнее, но будет следовать той же базовой стратегии. Получите имя метода, а затем найдите этот метод в MethodBase.DeclaringType.DeclaringType
тип (то есть тип, который содержит тип, сгенерированный компилятором). Обратите внимание, что при наличии более одной перегрузки для метода определение конкретной использованной перегрузки может быть сложным или непрактичным.
Это станет намного проще в C#7 с использованием локальных функций:
public Task DoAThingAsync()
{
var method = MethodBase.GetCurrentMethod();
LogMethod(method);
return doWork();
// Define inner function to actually do the work
async Task doWork()
{
// Do the work here
}
}
Вы уже можете достичь этого с помощью анонимных методов или делегатов, но это делает код очень понятным.