2008-11-10 106 views
1

在我寫的一段C#中,我需要以相同的方式處理具有相同簽名的多個方法。未來還可能有更多這些方法。相反,一遍又一遍地重複同一種邏輯的我還以爲下列內容:需要以相同方式處理的多種方法

private delegate bool cleanStep(BuildData bd, out String strFailure); 

List<cleanStep> steps = new List<cleanStep>(); 
steps.Add(WriteReadme); 
steps.Add(DeleteFiles); 
steps.Add(TFSHelper.DeleteLabel); 
steps.Add(TFSHelper.DeleteBuild); 

List<cleanStep>.Enumerator enumerator = steps.GetEnumerator(); 
bool result = true; 
while (result && enumerator.MoveNext()) 
{ 
    result = enumerator.Current.Invoke(build, out strFailure); 
    if (!result) 
    { 
     logger.Write(LogTypes.Error, strFailure); 
    } 
} 

我覺得這有一些不錯的功能,但同時也感到有點過enginered和混淆。

你能感謝更好的方法嗎?

BTW:

  • 它並不需要是事務性的。
  • strFailure沒有隱藏例外它包裝他們 完全必要時

感謝。

回答

9

爲什麼不使用foreach循環,只是打破? (我已經改名cleanStepCleanStep這裏俗套 - 我建議你做同樣的。)

foreach(CleanStep step in steps) 
{ 
    string failureText; 
    if (!step(build, out failureText)) 
    { 
     logger.Write(LogTypes.Error, strFailure); 
     break; 
    } 
} 

注意,這也遵循的IEnumerator<T>合同在您當前的代碼不 - foreach自動調用Dispose,和IEnumerator<T>執行IDisposable。在這種情況下,這不會成爲問題,但使用迭代器塊,disposal is used to execute finally blocks

+0

已經看起來更好。還了解到有關處理統計員的新情況。謝謝。我對break語句有點厭惡,但這裏確實有道理。 – KeesDijk 2008-11-10 14:06:34

2

您的解決方案既簡單又容易理解。我可以看到沒有理由做另一種方式:)

我建議的唯一的事情是用foreach循環替換你的迭代器,並打破一個錯誤。

0

重新模糊 - 井foreach與中斷可能會更清楚(加上它會Dispose()的枚舉,你不這樣做)。

實際上,一個 「PARAMS cleanStep []指標」 可能會有所幫助:

static bool RunTargets(params cleanStep[] targets) 
{ 
    // detail as per Jon's post 
} 

那麼你可以撥打:

bool foo = RunTargets(WriteReadme, DeleteFiles, 
       TFSHelper.DeleteLabel, TFSHelper.DeleteBuild); 
+0

謝謝,這實際上是我喜歡的功能之一。你可以重構這個函數,但也可以創建列表。 – KeesDijk 2008-11-10 14:11:34

0

我會返回一個例外對象而不是字符串。由於異常通常具有全局策略,因此我會編寫一些Exception擴展。現在,您可以:

static Exception Run(this IEnumerable<Step> steps) { 
    return 
     steps 
     .FirstOrDefault((step) => step(build) != null) 
     .LogIfFailure(); //or .ThrowIfFailure() 
} 

的擴展:

public static class ExceptionExtensions { 
    private static logger = new Logger(); 

    public static Exception LogIfFailure(this Exception e) { 
     if(e != null) 
      logger.Write(e.Message); 
     return e; 
    } 
    public static Exception ShowDialogIfFailure(this Exception e) { 
     if(e != null) 
      MessageBox.Show(e.Message); 
     return e; 
    } 
    public static void ThrowIfFailure(this Exception e) { 
     if(e != null) 
      Throw(e); 
    } 
} 
+0

謝謝。我喜歡乾淨的foreach,但是當一個步驟失敗時它不會停止。我知道我說它不需要事務性,但是當一個步驟失敗時,我們不希望它嘗試其餘的步驟。 – KeesDijk 2008-11-10 14:49:41

相關問題