2008-12-08 55 views
2

我有一個有一些常見錯誤處理代碼的類,並且我想傳入要調用的方法和參數,但我無法完成語法。我想要做的大致是這樣的:如何在C#中動態調用任何簽名的方法?

private void InvokeHelper(Delegate method, params object[] args) 
{ 
    bool retry = false; 

    do 
    { 
    try 
    { 
     method.DynamicInvoke(args); 
     retry = false; 
    } 
    catch (MyException ex) 
    { 
     retry = HandleException(ex); 
    } 
    } while (retry); 
} 

,然後可以做這樣的事情:

InvokeHelper(foo.MethodA, a, b, c); 
InvokeHelper(foo.MethodB, x, y); 

這得到一個編譯器錯誤轉換foo.MethodA和foo.MethodB到System.Delegate。我提出了下面的解決方法(我真的很喜歡它,因爲我對我的方法的參數進行了類型檢查),但是我很好奇是否有辦法做我最初嘗試做的事情?我知道我可以使用foo.GetType().GetMethod("MethodA")並援引,但我試圖避免反思。我主要只是想了解如何在.NET中動態調用方法。

解決方法:

private delegate void EmptyDelegate(); 

private void InvokeHelper(EmptyDelegate method) 
{ 
    bool retry = false; 

    do 
    { 
    try 
    { 
     method.Invoke(); 
     retry = false; 
    } 
    catch (MyException ex) 
    { 
     retry = HandleException(ex); 
    } 
    } while (retry); 
} 

然後調用:

InvokeHelper(delegate() { foo.MethodA(a, b, c); }); 
InvokeHelper(delegate() { foo.MethodB(x, y); }); 

回答

4

首先,你的簽名是

private void InvokeHelper(Delegate method, params object[] args) 

然而,你正在做,你必須將你的ARGS錯誤成一個數組來調用這個方法:

InvokeHelper(foo.MethodA, new object[] { a, b, c}); 

parms關鍵字告訴編譯器爲您做這件事;你可以調用這個方法正是如此:

InvokeHelper(foo.MethodA, a, b, c); 

其次,如果你的目標3.0或更高版本,不使用授權,使用操作:

private void InvokeHelper(Action method) 

,並調用它是這樣的:

InvokeHelper(()=> MyMethodToInvoke(a, b, c)); 

這只是一個更好的方法。


至於你爲什麼會遇到編譯器問題,它是因爲System.Delegates討厭我們。它是一個簡單的事實。那,並且因爲沒有從方法組到代表的隱式轉換。

+0

「沒有從方法組沒有隱式轉換爲委派」。答對了。一個方法有一個顯式聲明的參數列表。通常,編譯器通過檢查參數的類型來幫助您確定要使用的方法組中的哪個重載。這裏編譯器不能這樣做。 – 2008-12-08 16:24:14

2

這裏有一個重新寫,下面將的建議用行動:

private void InvokeHelper(Action method) 
    { 
     bool retry = false; 

     do 
     { 
      try 
      { 
       method(); 
       retry = false; 
      } 
      catch (MyException ex) 
      { 
       retry = HandleException(ex); 
      } 
     } while (retry); 
    } 

    public void Test() 
    { 
     FooClass foo = new FooClass(); 
     InvokeHelper(() => foo.MethodA(1, "b", 3)); 
     InvokeHelper(() => foo.MethodB(2, "y")); 
    } 
相關問題