2008-11-10 64 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

相关问题