设计模式与prolog和epilog

时间:2012-06-13 08:48:37

标签: c# design-patterns

我正在寻找可以实现一些prolog代码然后是epilog代码的设计模式。  让我解释一下:

我有一个函数(很多都是)amost做同样的事情:

这是presudo代码,但实际上它是用C#4.5编写的

public IDatabaseError GetUserByName(string Name)
{
  try
  {
      //Initialize session to database
  }
  catch (Exception)
  {
     // return error with description for this step
  }

  try
  {
       // Try to create 'transaction' object
  }
  catch(Exception)
  {
     // return error with description about this step
  }

  try
  {       
      // Execute call to database with session and transaction object
      //
      // Actually in all function only this section of the code is different
      //
  }
  catch(Exception)
  {
      // Transaction object rollback
      // Return error with description for this step
  }
  finally
  {
      // Close session to database
  }

   return everything-is-ok  
}

所以 - 你可以看到'prolog'(创建会话,事务,其他帮助函数)和'epilog'(关闭会话,回滚事务,清理记忆等等)对于 all 功能。

一些限制:

  • 我想在函数中保持会话和事务对象创建/销毁过程,而不是在ctor中
  • 自定义代码(在中间运行)必须包含在try / catch中,并针对不同情况返回不同的错误
  • 我对任何Func<>,Action<>开放优选的任务<>功能建议

    有关设计模式或代码重构的任何想法吗?

2 个答案:

答案 0 :(得分:3)

这可以通过使用IDisposable对象来实现,例如:

using(var uow = new UnitOfWork() )
using(var t = new TransactionScope() )
{
   //query the database and throws exceptions
   // in case of errors
}

请注意,TransactionScope类是System.Transaction中的一个开箱即用的类,它不仅适用于数据库连接。 在UnitOfWork constructor中执行“Prologue”代码(即打开连接...),在Dispose中执行结尾部分。通过在出现错误时抛出异常,您确定无论如何都会调用结尾部分。

答案 1 :(得分:2)

听起来你正在寻找Template Method Pattern

模板方法模式允许您通过仅提取方法中不同的部分来减少类似方法中的重复代码量。

对于这个特定的例子,你可以编写一个方法来完成所有繁琐的工作,然后调用一个回调来完成有趣的工作......

// THIS PART ONLY WRITTEN ONCE
public class Database
{
    // This is the template method - it only needs to be written once, so the prolog and epilog only exist in this method...
    public static IDatabaseError ExecuteQuery(Action<ISession> queryCallback)
    {

        try
        {
            //Initialize session to database
        }
        catch (Exception)
        {
            // return error with description for this step
        }

        try
        {
            // Try to create 'transaction' object
        }
        catch(Exception)
        {
            // return error with description about this step
        }

        try
        {       
            // Execute call to database with session and transaction object
            //
            // Actually in all function only this section of the code is different
            //
            var session = the session which was set up at the start of this method...

            queryCallback(session);
        }
        catch(Exception)
        {
            // Transaction object rollback
            // Return error with description for this step
        }
        finally
        {
            // Close session to database
        }

        return everything-is-ok
    }
}

这是用法:

// THIS PART WRITTEN MANY TIMES
IDatabaseError error = Database.ExecuteQuery(session =>
{
    // do your unique thing with the database here - no need to write the prolog / epilog...

    // you can use the session variable - it was set up by the template method...

    // you can throw an exception, it will be converted to IDatabaseError by the template method...
});

if (error != null)
    // something bad happened!

我希望这次能更好地解释:)