2

プロローグ コードとエピローグ コードを実装できる設計パターンを探しています。説明させてください:

私はほとんど同じことをする機能(それらの多く)を持っています:

これは前提コードですが、実際には 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  
}

したがって、ご覧のとおり、「プロローグ」(セッションの作成、トランザクション、その他のヘルパー関数) と「エピローグ」(セッションのクローズ、トランザクションのロールバック、メモリの消去など) はすべての関数で同じです。

いくつかの制限:

  • セッションおよびトランザクション オブジェクトの作成/破棄プロセスをctor ではなく関数に保持したい

  • カスタム コード (途中で実行されるコード) は、try/catch でラップし、さまざまな状況でさまざまなエラーを返す必要があります。

  • Func<>、Action<> の望ましい Task<> 関数の提案を受け付けています。

    デザインパターンやコードリファクタリングのアイデアはありますか?

4

2 に答える 2

3

これは、次のように IDisposable オブジェクトを使用して実現できます。

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

TransactionScopeクラスは、DB 接続だけでなく、System.Transaction にあるすぐに使用できるクラスであることに注意してください。UnitOfWorkconstructorで「プロローグ」コードを実行し (つまり、接続を開く...)、Disposeエピローグ部分を実行します。エラーが発生したときに例外をスローすることで、エピローグ部分がとにかく呼び出されることを確認できます。

于 2012-06-13T08:57:01.303 に答える
2

テンプレートメソッドパターンを探しているようです。

テンプレートメソッドパターンを使用すると、メソッドの異なる部分のみを抽出することで、同様のメソッドで重複するコードの量を減らすことができます。

この特定の例では、すべてのうなり声の作業を実行するメソッドを記述してから、コールバックを呼び出して興味深い作業を実行できます...

// 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!

今回はもっとよく説明できたと思います:)

于 2012-06-13T09:29:05.130 に答える