2009-07-25 6 views
0

私はすべてのボタンの基本カスタムページにイベントを登録するという考えがありました。私はそれが保存または編集であったかどうかを確認し、承認と検証を行うことができます。派生したページは、そのページに保存するための詳細を行うためにclickイベントを処理します。どのイベントが最初に起きるかはわかりませんでした。親ページが最初に実行される場合、IsAuthorizedまたはIsValidatedプロパティを設定し、派生した各ページのクリックハンドラでそれを確認することで、期待される動作を得ることができます。C#で特定の順序でイベントを処理する方法を教えてください。

とにかく、基本ページのイベントハンドラを実行して最初に完了させる方法はありますか、これを救済する方法はありますか?

EDIT:アプリケーションのすべての編集/保存/更新ボタンハンドラにボイラープレートコードを追加する必要がない、シンプルなデザインを見落としていますか?そして、あるイベントハンドラが別のイベントハンドラと通信する正しい方法は何ですか?たとえば、基本ページが成功または失敗の検証を伝達する必要がある場合、派生クラスは保存の成功または失敗を伝える必要があるため、監査に記録することができます。

//Base page-- seems like this will work if events happen in order of wireup. 
protected override void OnInit(EventArgs e) 
{ 
    foreach (Control possibleButton in Controls) 
    { 
     if(possibleButton is Button) 
     { 
      Button button = (Button) possibleButton; 
      button.Command += ButtonCommandPreconditions; 
     } 
    } 
    base.OnInit(e); 
    foreach (Control possibleButton in Controls) 
    { 
     if(possibleButton is Button) 
     { 
      Button button = (Button) possibleButton; 
      button.Command += ButtonCommandPostconditions; 
     } 
    } 
} 

void ButtonCommandPreconditions(object sender, CommandEventArgs e) 
{ 
     if(e.CommandName=="Save" || e.CommandName=="Edit") 
     { 
      //Stuff that needs to happen before other handler 
      //Validate, display failures-- maybe set IsValdated property 
      //Check for POST/GET, throw exception on GET. 
      //Check for ID, throw exception on anonymous user 
      //Check for authorization 
      //Display authorization failures-- maybe set IsAuthorized property 
     } 
} 

void ButtonCommandPostconditions(object sender, CommandEventArgs e) 
{ 
     if(e.CommandName=="Save" || e.CommandName=="Edit") 
     { 
      //Stuff that needs to happen *after* other handler 
      //Log save 
     } 
} 

編集:利きがwireupの順に処理されることになっているそのイベントを反映する 変更されたコード。

答えて

3

"保存"(と同様のイベント)ロジックを独自のクラス階層に分けるように指示するのとは別に、ソリューションを提供する準備ができていません(デザインの理解が必要なので)。イベントハンドラから1つの人生にそれらを呼び出す。しかし、元の質問にコメントを付けることができます(編集前の太字)。設定の問題は、特定の順序でイベントを発生させることができますが、.Net Frameworkのイベントは保証されていません。彼らはあなたの開発マシンでテストするときに順序付けられているように見えるかもしれませんが、実用的な展開では、システムの負荷が高くなる瞬間に、イベントは他の操作に優先して延期される最初のものになります。イベント到着はリスナーに本質的にランダムになる可能性があります。

イベントを受信する順序に基づいて論理を構築することは絶対に避けてください。各イベントは現在の状態のみを考慮する必要があります。他のイベントについては何も想定できません。あなたのイベントの連鎖は、あなたが一番必要なときに壊れます。

+0

ああ!これは私の基本的な考え方に欠陥があることを私に確信させる。ありがとう!それは私に盲目的な路地を下る多くの努力を救った。 – MatthewMartin

+0

あなたは他人からそれを聞く必要があると思いますか? – womp

1

イベントハンドラは、追加された順に呼び出されます。したがって、親ハンドラが最初に追加されることを保証できれば、あなたは大丈夫です。

基本クラスのButtonコマンドイベントを処理して、新しいButtonCommandイベントを実装した派生クラスにそれらを委譲することで、頭痛を軽減することができます。既存の派生コードからの唯一の真の変更は、派生イベントハンドラの「送信者」パラメータに細心の注意を払うことです。たとえば:

class BaseClass 
{ 
    public event CommandEventHandler ButtonCommand = delegate { }; 

    protected override void OnInit(EventArgs e) 
    { 
     foreach (Control possibleButton in Controls) 
     { 
      if (possibleButton is Button) 
      { 
       Button button = (Button) possibleButton; 
       button.Command += AnyButtonCommandHandler; 
      } 
     } 
     base.OnInit(e); 
    } 

    void AnyButtonCommandHandler(object sender, CommandEventArgs e) 
    { 
     // validation logic. if fails, return. 

     ButtonCommand(sender, e); 
    } 
} 

class DerivedClass : BaseClass 
{ 
    public DerivedClass() 
    { 
     base.ButtonCommand += base_ButtonCommand; 
    } 

    void base_ButtonCommand(object sender, CommandEventArgs e) 
    { 
     if (sender == button1) { ... } 
     else if (sender == button2) { ... } 
     // etc. 
    } 
} 

またprotected void OnButtonCommand(object sender, CommandEventArgs e)ButtonCommandイベントを置き換えることを検討(あるいはその両方を行う)ことができ;派生クラスでOnButtonCommandを単にオーバーライドすることができます。

5

イベントは単なるマルチキャストデリゲートなので、イベントハンドラはイベントに追加された順に発生します。

私は正直言ってこれに反対します。たとえ動作しても、かなり不透明です。同じイベントを処理する異なるクラスの2つの別々のイベントハンドラがあり、それらの間には明確なつながりがありません。

独自の処理を行う前に、継承した各ページから処理するために、親ハンドラにイベントをバブルする方が良いでしょう。そうすれば、明確な結びつきがあり、コードは簡単に実行でき、イベントの順序付けに関する前提に頼る必要はありません。新たな疑問について


EDIT:

そして 相互に通信するために1つの イベントハンドラのための正しい方法は何ですか?

あなたはthis post.イベントハンドラでの私の答えは、実際に点火順序の保証がないよう、ASP.Net(少なくともWebBrowserコントロール/ページライフサイクルイベントハンドラの)中で互いに通信することを意図していないはずです。兄弟イベントハンドラに設定されている情報に依存するイベントハンドラがある場合、おそらくデザインに欠陥があります。例えば

ベースページが に必要成功または失敗 検証を伝える、派生クラスは、それが 監査に記録できるように保存 の成功または失敗を伝える する必要があります。

実際にこれを処理する方法はいくつかあります。まずは、派生したページでオーバーライドできる抽象メソッドまたは仮想メソッドを基本クラスで呼び出すだけです。ベースページのボタンクリックハンドラ中に、すべての検証を行い、派生したページの抽象的な "DoSave()"メソッドを呼び出し、成功したことを確認します。

あなた自身のイベントを書き込んで、必要に応じてイベントを発生させてください。基本クラスに「検証」イベントを作成し、応答が必要な場合は、派生したページにサブスクライブさせます。検証が完了したら、基本クラスがそれを発生させるようにしてください。ベースクラスに "Saved"イベントを作成し、それに対するイベントハンドラを作成し、ベースクラスにサブスクライブさせます。保存が完了したら、derived classes raise the eventを持ってください。これで基本クラスがそのクラスのロギングを処理できます。


私は基本クラスのボタンのクリックに非常に多くのものを読み込んでいるように思われることを追加したいと思います。ページのレンダリング時に匿名IDとGET/POSTチェックを行い、権限がない場合はボタンを表示しないでください。

関連する問題