1

次のシナリオを想像してみてください。コントロール A とコントロール B を含む Page1 があります。

コントロール A にボタンがあり、このボタンをクリックすると、コントロール B が反応するとします。しかし、これを抽象的な方法で行いたいと考えています。つまり、コントロール A について何も知らないコントロール B を持つことはできず、その逆も同様です。

そうすれば、これらのコントロールを分離して開発し、単体テストによってそれらを駆動できます。

今、私は解決策を持っていると思いました。皆さんがそれについてどう思うか知りたいだけです.

コントロール A のボタン クリックで、セッションに「メッセージ」を配置します。つまり、Session["MESSAGES"] = "ControlA_Click" です。

Page1 の Page_LoadComplete() で、次のように ProcessMessages を呼び出します。

            List<Message> messages = SessionMessages.GetMessageList(Page);
        foreach(Message m in messages)
        {
            //Get Controls
            ControlA controlA = FindControl("controlA") as ControlA;
            controlA .ProcessMessage(m);

            ControlB controlB = FindControl("controlB") as ControlB;
            controlB.ProcessMessage(m);
      }

ControlB の ProcessMessage() メソッドでは、次のように、ControlB が関心のあるメッセージに反応できます。

    if (m.MessageName == SessionMessages.C_MESSAGE_SEARCH)
{
    this.Visible = true;
}

私には、これはうまくいくようです。これにより、これらのコントロールを互いに完全に個別に開発できますが、抽象レベルでのコントロール間の通信も可能です。

このクラッシュを引き起こす可能性があると私が考えることができる唯一のことは、おそらくページとユーザー コントロールに関連する ASP.NET ライフサイクルです。私がそれを理解する方法は、所有するページで Page_LoadComplete() が呼び出される前に、すべてのイベントがコントロールで処理されている必要があるということです。

考え?

4

7 に答える 7

6
  1. コントロール A はイベントを発生させる必要があります
  2. コントロールを収容するページは、イベントをサブスクライブし、他のコントロールで適切なメソッドを呼び出します
  3. コントロール B は message() を処理する必要があります
于 2008-11-11T18:08:49.807 に答える
2

セッションの興味深い悪用...

代わりに、メッセージ キューをホスティング ページに所属させることもできます。

代わりに、コントロールを「スマート」にするのではなく、ホスト ページにメッセージに応答してコントロールに何かをさせることをお勧めします。ボタンを「スマート」にする必要はありません。

于 2008-11-11T18:03:14.980 に答える
2

Briggie がほのめかしているように、これこそまさに Model-View Presenter のすべてです。.NET でのMVPに関する記事を参照してください。

理想的には、すべてを分離したときにできることの例として、MVC フレームワークを検討する必要があります。

私が通常行うことは、ボタン クリック イベントで次のようなドメイン固有のイベントを発生させることです。


private void ControlA_OnClick(..)
{
  if(LoginRequested != null)
    LoginRequested(this, loginObj);
}

そうすれば、誰かがボタンをクリックする理由が明確になり、分離を思いとどまらせることができます。

于 2008-11-11T18:31:22.863 に答える
1

これはデータバインディングの目的ではありませんか? コントロール A は、モデルを更新するイベントに応答し、その依存関係で databind を呼び出します。

メッセージング システムを作成する場合は、パブリッシャーとサブスクライバーがお互いについて知る必要はなく、メッセージ自体だけを知る必要があるように設計します。次のようなインターフェイスを作成します。

public interface IHandle<T> where T:IMessage
{
     void Process(T message)
}

どのコントロールがそれを実装しているかを発見し、messagetype->handlers のマップを作成する方法が必要になります。メインの DI フレームワークが ASP .NET コントロールへのプロパティ インジェクションを処理する方法を見て、これをどのように達成できるかを確認してください。次に、そのメッセージを処理できるすべてのコントロールにメッセージをディスパッチする役割を担う単一の SendMessage メソッドを使用できます。この種のパターンは、フォーム UI でよく見られます。

于 2008-11-11T18:18:36.917 に答える
1

あなたが持っているのはほとんどEventBrokerです。リクエストにまたがる必要がないため、セッションはこれに適した場所ではないと思います。HttpContextは機能する可能性がありますが、IHttpModules と IHttpHandlers の間でメッセージ バスを共有したくない場合は、カスタム コントロールが Page インスタンスをキャストできる基本 Page クラスを使用するかのどちらかです。

interface IEventBroker {
 void Send(Message m);
}

class ControlA {
  void MyButton_Click(object sender, EventArgs e) {
     var eb = this.Page as IEventBroker;
     if (eb != null) eb.Send(new Message());
  }
}

または、コントロールに EventBroker への参照を与えます。この場合、おそらく EventBroker 自体をコントロールにして、各コントロールに ID を与えて、Page.FindControl を使用できるようにします。

于 2008-11-11T21:03:58.297 に答える
0

Managed Extensibility Framework Contrib プロジェクトを確認してください。彼らはあなたが望むものだけのサンプルウェブサイトを持っています.

于 2008-11-11T18:16:15.890 に答える
0

このアプローチには、次のようないくつかの問題があります:
- 「イベント」はコンパイル時に検証されません (イベント名を簡単に間違えて、実行時または最悪の場合にこれを見つけることができます)
- セッションを通信要素で埋める
- コントロール名を配置する必要があります文字列として - これらのイベントのサブスクライバーであるコントロールが複数ある場合、コントロールが難しくなる可能
性があります - コントロール間でパラメーターを送信する必要がある場合、ソリューションの管理がより難しくなります

より良いアプローチは、コントロールでイベントを宣言することにより、組み込みのイベント メカニズムを使用することです。

public event EventHandler SpecialClick;

何かを行う必要がある各コントロールは、このイベントをサブスクライブします

controlA.SpecialClick += new EventHandler(controlA_SpecialClick)

通常の dot.net イベントを使用します。

于 2008-11-11T18:19:00.660 に答える