2015-01-19 5 views
0

В моем приложении у меня есть небольшой журнал действий. В там я сохранить последние несколько звонков определенных методов в моем приложении, как это:MethodBase Объект async-функции

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 для async. С тех пор MethodBase.GetCurrentMethod() возвращает функцию MoveNext, а не функцию, которую я назвал.

Есть ли способ добраться до фактического объекта MethodBase вызываемой функции, будь то во время сохранения или вызова, не имеет значения.

С наилучшими пожеланиями lolsharp

+0

Информация, предоставленная вами, недостаточна. –

ответ

0

ли вам действительно нужно MethodBase объект? Или достаточно просто записать достаточно подробностей, чтобы человек мог выяснить, какой именно метод?

Если последнее, то это довольно просто: обратите внимание, что выполняемый метод фактически содержится в классе, сгенерированном компилятором, где само имя класса содержит имя метода, который компилятор переписал для создания этого класса.

Так в вашем saveLastAction() метода, когда предположительно вы входите значение MethodBase.Name свойства, вы должны сначала проверить значение MethodBase.DeclaringType.Name, и если это выглядит как <SomeMethodName>d_5 (где специфика после закрывающей угловой скобки может меняться, а), вы можете используйте текст в угловых скобках для имени метода вместо значения свойства MethodBase.Name.

Обратите внимание, что только компилятор может генерировать имена классов с этими угловыми скобками, поэтому вам не нужно беспокоиться о получении ложных срабатываний.

В качестве дополнительного бонуса это позволит вашему протоколу ведения журнала работать и с методами итератора. :)

Если вам нужен сам объект MethodBase, это немного сложнее, но будет следовать той же базовой стратегии. Получите имя метода, а затем посмотрите, что этот метод находится в MethodBase.DeclaringType.DeclaringType (т. Е. Тип, содержащий тип, сгенерированный компилятором). Обратите внимание, что если существует более одной перегрузки для метода, определение конкретной перегрузки, которая была использована, может быть сложной или непрактичной.

2

Я создал небольшую функцию справки:

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. В итоге очень похоже на подход Петерса.

+0

Я пытался найти альтернативу как вопрос, и это сработало чудесно. Благодаря! –

0

Это собирается к получить намного проще в C#7 using local functions:

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 
    } 
} 

Вы уже можете добиться этого с анонимными методами или делегатами, но это делает код очень CLEARN.