C# 开始、完成和失败方法中周围代码的设计模式
假设我要运行不同的任意代码段,但在每个代码段之前,我必须运行C# 开始、完成和失败方法中周围代码的设计模式,c#,design-patterns,C#,Design Patterns,假设我要运行不同的任意代码段,但在每个代码段之前,我必须运行Start()方法,然后在每个代码段之后,我需要运行Complete()方法。但是,如果在代码部分抛出异常,我希望运行Fail(字符串消息)方法,而不是Complete()。是否有一种设计模式可以优雅地封装它,使其整洁且易于重复 例如,假设我有一个名为Thing的类型,它包含一个Start()方法,该方法向日志数据库表中添加一行以反映任务正在进行中,一个Complete()方法更改该行以反映任务已完成和失败(字符串消息)更改行以反映任务
Start()
方法,然后在每个代码段之后,我需要运行Complete()
方法。但是,如果在代码部分抛出异常,我希望运行Fail(字符串消息)
方法,而不是Complete()
。是否有一种设计模式可以优雅地封装它,使其整洁且易于重复
例如,假设我有一个名为Thing
的类型,它包含一个Start()
方法,该方法向日志数据库表中添加一行以反映任务正在进行中,一个Complete()
方法更改该行以反映任务已完成和失败(字符串消息)
更改行以反映任务失败的方法。不过,这些只是示例,它们可以执行任何设置和整理类型的任务
简单的实现可能只是手动调用这些方法:
public void DoStuff()
{
var thing = new Thing();
thing.Start();
try
{
DoImportantStuff();
thing.Complete();
}
catch (Exception e)
{
thing.Fail(e.Message);
}
}
但是如果我不得不在很多不同的地方重复这一点,它最终会产生相当多的重复,可能很容易忘记调用Complete
,或者以某种微妙的方式将其搞糟
在C#中,有使用
模式,它提供了一种封装大部分内容的好方法。例如,如果我的东西类型如下所示:
public class Thing : IDisposable
{
public Thing(){
Start();
}
private void Start() { /* start */ }
private void Complete() { /* complete */ }
public void Dispose()
{
Complete();
}
}
public class Thing
{
private void Start() { /* start */ }
private void Complete() { /* complete */ }
private void Fail(string message) {}
public void DoAction(Action action)
{
this.Start();
try
{
action();
this.Complete();
}
catch (Exception e)
{
this.Fail(e.Message);
}
}
}
Thing thing = new Thing();
thing.DoAction(this.DoStuff);
我的DoStuff()
方法现在可以简化为:
public void DoStuff()
{
using(new Thing())
{
DoImportantStuff();
}
}
这是更好的。但是如果抛出异常,它不允许调用Fail
而不是Complete
,因为(我想!)实际上是在Finally
块中调用Dispose
方法
我曾想过在using
块中设置一个try/catch
,然后在catch
块中设置一个东西。hasfiled
标志,然后在Dispose
方法中使用它来决定是完成还是失败。但这似乎有点棘手,我希望东西的消费者必须尽可能少地做一些事情,使其正常工作
那么,是否有一种设计模式可以封装我想要做的事情,并避免每次都需要手动编写try\catch
public class Thing : IDisposable
{
public Thing(){
Start();
}
private void Start() { /* start */ }
private void Complete() { /* complete */ }
public void Dispose()
{
Complete();
}
}
public class Thing
{
private void Start() { /* start */ }
private void Complete() { /* complete */ }
private void Fail(string message) {}
public void DoAction(Action action)
{
this.Start();
try
{
action();
this.Complete();
}
catch (Exception e)
{
this.Fail(e.Message);
}
}
}
Thing thing = new Thing();
thing.DoAction(this.DoStuff);
然后像这样使用它:
public class Thing : IDisposable
{
public Thing(){
Start();
}
private void Start() { /* start */ }
private void Complete() { /* complete */ }
public void Dispose()
{
Complete();
}
}
public class Thing
{
private void Start() { /* start */ }
private void Complete() { /* complete */ }
private void Fail(string message) {}
public void DoAction(Action action)
{
this.Start();
try
{
action();
this.Complete();
}
catch (Exception e)
{
this.Fail(e.Message);
}
}
}
Thing thing = new Thing();
thing.DoAction(this.DoStuff);
使用
该模式称为“模板方法”。您可以在标题“面向方面编程”下找到您的实现。
()这实际上并不是对所问问题的回答。虽然这可能不是一种设计模式,但我认为这很容易成为具有一流函数的语言中最优雅的解决方案,因此我将其标记为已接受。在没有函数传递的语言中,我想模板方法模式是最好的选择如果你要链接到某个东西,请在你的实际答案中包含一个代码示例,因为链接可能会过期。提及模板方法模式很好,尽管我不确定该链接是否有用,因为它没有明确讨论模板模式,并且在web服务细节方面有点陷入困境。wikipedia的文章()提供了一个更好的总结:“在软件工程中,模板方法模式是一种行为设计模式,它定义了操作中算法的程序框架,将某些步骤推迟到子类。它允许在不改变算法结构的情况下重新定义算法的某些步骤。”看看面向方面编程()。看起来您可以将entry/error/leave方法定义为连接点。