2011-03-19 26 views
19

Bir eylemden bir yöntem adı almak mümkün mü? Biliyorum, her zaman bir ip geçirebilirim, ama biraz daha zeki bir şey umuyordum.Get Yöntem Adı İşlemden

public bool DeviceCommand(Action apiCall) 
    { 
     //It would be nice to log the method name that was passed in 
     try 
     { 
      apiCall(); 
     } 
     catch (Exception exc) 
     { 
      LogException(exc); 
      return false; 
     }   

     return true; 
    } 

Kullanımı şuna benzer:

void MyMethod() 
(
    DeviceCommand(() => api.WriteConfig(config)); 
) 
+2

Bu bir LINQ ifadesi, sizce ne bildirilmeli? DeviceCommand (() => (standart? Api.WriteConfig (config): api.WriteExtendedConfig (config))); ' – tvanfosson

+0

Olsaydı, ne tür bir sıralama yapmadan istediğimi gerçekleştirmenin imkansız olduğunu söyler misiniz? parametre bir LINQ ifadesi olduğu için mi? – Robert

+1

Hayır, sadece örneğiniz basit olduğundan, genel sorunun nedeni, herhangi bir nitelendirici kod bloğu dahil olmak üzere çeşitli şeyler olabileceği için değildir. Muhtemelen çağrıyı kaydetmemekle iyi olurdum, ancak bir istisna varsa yığın izlemeyi dahil ettiğimi kontrol ediyorum. Ya da sadece aramaları takip etmek istiyorsanız, her bir yöntemde çağrıyı kaydedin. – tvanfosson

cevap

18

DeviceCommand'ın isimlendirmeleri hep parametre olarak bir ifade ağaç almak o zaman DeviceCommand değiştirebilir formu

DeviceCommand(() => someObject.SomeMethod(parameters)); 

arasında olacak.

Elbette
public bool DeviceCommand(Expression<Action> apiCallExp) 
{ 
    var methodCallExp = (MethodCallExpression) apiCallExp.Body; 
    string methodName = methodCallExp.Method.Name; 
    // do whatever you want with methodName 

    Action apiCall = apiCallExp.Compile(); 
    try 
    { 
     apiCall(); 
    } 
    catch(Exception exc) 
    { 
     LogException(exc); 
     return false; 
    } 

    return true; 
} 

, bina: Bu istediğiniz bilgi almak (bu durumda, dize "birYöntem"), sonra bir temsilci içine ağacı derlemek ve çalıştırmak için ağaca detaya olanak sağlayacak ve her seferinde bir ifade ağacı derlemek önemli bir performans sorunu olabilir (ya da değil - sadece ne sıklıkta DeviceCommand çağrılır). Performans etkilerinin (ve bu yaklaşımın genel "hack" zaafiyetinin) durumunuza değip değmeyeceğine karar vermelisiniz.

15

Evet vardır: Action.Method.Name

Ancak bu sadece çalışır sen bir lambda ifadesi olarak, bir yöntem grubu olarak Eylem parametresinde geçirirseniz :

class Program 
{ 
    static void SomeActionName(){} 

    static void Main(string[] args) 
    { 
     LogMethodName(() => SomeActionName()); // <Main>b__0 
     LogMethodName(SomeActionName); // SomeActionName 

     var instance = new SomeClass(); 
     LogMethodName(() => instance.SomeClassMethod());; // <Main>b__1 
     LogMethodName(instance.SomeClassMethod); // SomeClassMethod 


    } 

    private static void LogMethodName(Action action) 
    { 
     Console.WriteLine(action.Method.Name); 
    } 
} 

class SomeClass 
{ 
    public void SomeClassMethod(){} 
} 
+0

Action.Method.Name DeviceCommand() içerdiği yöntemin anonim yöntem adını döndürüyor, gerçek api çağrısı değil. Örneğin, Action.Method.Name WriteConfig yerine MyMethod değerini döndürür. Örnek kullanımımı bunu göstermek için güncelledim. – Robert

+0

@Aaron, @Robert: Sadece bunu test ettim, sadece Action parametresini bir lambda ifadesi olarak değil, bir 'method group' olarak geçirirseniz çalışır. İkincisi için, bir 'İfade' içinde geçen Aarons yaklaşımına ihtiyacınız var. – jeroenh

İlgili konular