2010-06-16 61 views
0

我可能會失去這個陰謀,但我希望有人能指出我的方向。Generic Func <>作爲基本方法的參數

我想要做什麼?

我想寫一些基本的方法,它採取Func <>和Action,以便這些方法處理所有的異常處理等,所以它不會重複遍佈整個地方,但允許派生類指定什麼操作想要執行。

到目前爲止,這是基類。

public abstract class ServiceBase<T> 
{ 
    protected T Settings { get; set; } 

    protected ServiceBase(T setting) 
    { 
     Settings = setting; 
    } 

    public void ExecAction(Action action) 
    { 
     try 
     { 
      action(); 
     } 
     catch (Exception exception) 
     { 
      throw new Exception(exception.Message); 
     } 
    } 

    public TResult ExecFunc<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> function) 
    { 
     try 
     { 
      /* what goes here?! */ 
     } 
     catch (Exception exception) 
     { 
      throw new Exception(exception.Message); 
     } 
    } 
} 

我想執行在派生類中按以下方式操作(這似乎工作):

public void Delete(string application, string key) 
{ 
    ExecAction(() => Settings.Delete(application, key)); 
} 

而且我想以同樣的方式在派生類中執行函數求但是對於我來說,我似乎無法鍛鍊在基礎課上放置什麼東西。

我希望能夠調用它以下面的方式(如果可能):

public object Get(string application, string key, int? expiration) 
{ 
    return ExecFunc(() => Settings.Get(application, key, expiration)); 
} 

我在想太瘋狂了或這可能嗎?預先感謝所有的幫助。

+0

我不明白。異常處理程序正在重新拋出異常,但沒有堆棧跟蹤? – Amy 2010-06-16 15:25:59

+0

作爲一個附註,'throw new Exception'在這裏可能是錯誤的。至少你想把'ex'視爲內在的例外。另一種選擇是'拋出;'重新拋出它而不重置堆棧,或者如果你沒有做任何事情,就不要捕獲它。 – Kobi 2010-06-16 15:27:59

+0

感謝您的迴應,請不要擔心它將要更新的異常處理。這只是一個例子:-) – WestDiscGolf 2010-06-16 15:51:11

回答

3
public void Delete(string application, string key) 
{ 
    ExecAction(() => Settings.Delete(application, key)); 
} 

public object Get(string application, string key, int? expiration) 
{ 
    return ExecFunc(() => Settings.Get(application, key, expiration)); 
} 

// ... 

public TResult ExecFunc<TResult>(Func<TResult> func) 
{ 
    try 
    { 
     return func(); 
    } 
    catch (Exception exception) 
    { 
     throw new Exception(exception.Message); 
    } 
} 

順便說一句,你的異常處理看起來有點狡猾:首先,這不是好的做法趕上Exception本身。請考慮捕獲更具體的異常。其次,你在catch塊中拋出一個新的異常,這意味着你正在失去原始異常的堆棧跟蹤等。您應該使用throw;替代重新拋出原始異常。 (這裏假定你的catch模塊正在做一些有用的工作,如果你所做的只是捕捉和拋擲,那麼就把try...catch模塊完全拋棄掉。)

+0

感謝您的迴應;已經工作過。我知道在發佈之前我錯過了之前的一些嘗試。我同意在初始開發階段純粹插入的異常處理,這將被整理出來:-) – WestDiscGolf 2010-06-16 15:48:11

1
public TResult ExecFunc<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> function, T1 t1Param, T2 t2Param, T3 t3Param) 
{ 
    try 
    { 
     return function(t1Param, t2Param, t3Param); 
    } 
    catch (Exception exception) 
    { 
     throw new Exception(exception.Message); 
    } 
} 

然後調用它像這樣:

public object Get(string application, string key, int? expiration) 
{ 
    return ExecFunc(Settings.Get, application, key, expiration); 
} 
0
public object Get(string application, string key, int? expiration) 
{ 
    object result = null; 
    ExecAction(() => result = Settings.Get(application, key, expiration)); 
    return result 
} 
4

首先,你在這裏做例外情況可能是一個壞主意。所有例外的一般情況幾乎都不是你想要的。

但對於一般你在做什麼,你已經與Action解決了這個問題。爲了方便,你只需要爲Func細化調用Action版本:

public static TResult ExecFunc<TResult>(Func<TResult> func) 
{ 
    TResult result = default(TResult); 
    ExecAction(() => result = func()); 
    return result; 
} 

沒有必要提供一種方法,通過論證,因爲封鎖已經解決了這個問題:

var someData = "Hi!"; 
var result = ExecFunc(() => SomeOtherMethod(someData)); 
// the lambda can close over the local variables of the outer scope 

注我是如何使方法成爲靜態的,因爲它看起來像ExecAction也可以是靜態的,因爲它沒有引用任何實例成員。如果方法是靜態的,可能會更清楚地將它們移動到一個單獨的static類中。

+0

感謝您的迴應; +1有趣的ExecAction功能的重用:-)至於異常處理,這將是固定的,它只是添加到初始開發階段。它的下一個被修復。 – WestDiscGolf 2010-06-16 15:49:47

+1

酷 - 這就是爲什麼使ExecFunc調用ExecAction好,所以當你改變包裝代碼時你只需要做一次。 :) – 2010-06-16 16:10:36

相關問題