14

大規模なシステムMVCベースには、データの編集を担当するビューとそのデータを表示するビューがあります。

例:UserManagementViewおよびUserSelectionView

各サブシステムは、別のサブシステムが同じデータに変更を加えた後、コントローラーがデータ更新が必要かどうかを知るために、データ更新が必要かどうかを知る必要があります。

これについての私の考えは、オブザーバーパターン(c#に統合されている)のようなものであり、すべてのコントローラーがリスナーになり、最終的にデータ操作が発生したことが通知されます。

BindingList<>たとえば、ListChangedイベントを提供します。同様に、データ構造ごとにインターフェースを作成し、変更についてコントローラーに通知することができます。これはオーバーヘッド(IMO)を追加し、このソリューションを大規模なシステムで維持するのは難しいと思います。また、とにかくデータを更新することはソリューションではありません。

この種のシナリオで役立つアーキテクチャ設計はどれですか?

4

4 に答える 4

5

この質問は、モデルパーツなしでMVCを使用しようとしているように聞こえます。誤解している場合は、質問を編集して実際のユースケース(例)を含めると、コンテキストを理解するのに役立つ場合があります。

ただし、一般的には、コントローラーに実際に永続化/保存されるものはありません。したがって、「更新」または「通知」を必要とするコントローラーには何も存在しないはずです(つまり、データがありません)。むしろ、データはすべてのデータを管理する別の「モデル」レイヤーにある必要があります。次に、ビューがモデルレイヤーから読み取られ、そのビューのデータが取得されます。

簡単な復習については、 MVCのウィキペディアページをチェックしてください。このページには、優れた古典的なMVCフローチャートとコンポーネントの相互作用に関する簡単な説明があります。

議論の例

この問題を理解するために、例を考えてみましょう。

アプリケーションにユーザーのリストがあるとしましょう。このリストは次の場所に表示される場合があります。

  • マスター管理者リストビュー
  • 管理者編集ユーザービュー
  • ユーザーの個人プロフィールビュー
  • おそらくもっとある?

これらの各ビューは、モデルレイヤーからのデータを要求し、画面に何かを表示します。

ここで、1人のユーザーのプロファイルに変更がコミットされたとしましょう。これは、モデルにいくつかの変更を適用するために必要な作業を行うコントローラーメソッドを介して実行されます。

私の理解では、これらのすべてのビューを更新して、その変更を反映する必要があります。つまり、ビューはモデルからデータをリロードする必要があります。コントローラーがこのリロード/リフレッシュをトリガーしたとしても、コントローラー自体からこのデータを取得するべきではありません。むしろ、コントローラーメソッドがモデルレイヤーからのクエリを容易にする場合があります。重要な部分は、アプリケーション全体で複数のコントローラーにデータの複数のコピーを保持していないことです。永続性はモデルレイヤーに集中化されます。

WinFormsの場合、UIコンポーネントがそのインターフェイスを認識し、それに応じて更新するように構築されている場合、モデルレイヤーは前述のINotifyPropertyChangedインターフェイスのようなものを提供できる可能性があります。しかし、それはかなりプラットフォームに依存するアプローチです。

よりプラットフォーム/コンテキストにとらわれないアプローチは、すでに述べたpub-sub(publish-subscribe)パターンです。この場合、モデルに変更を加える各コントローラーメソッドは、その変更の通知も公開します。そのデータのすべてのビューは、モデルレイヤーからビューのデータを更新/再ロードすることにより、そのような通知をリッスンして応答できます。

于 2012-08-29T06:45:39.593 に答える
3

INotifyPropertyChangedWPFとMVVMの組み合わせは、さらに大きく依存していることを私は知っていますINotifyCollectionChanged。たぶん、この単純なインターフェースはあなたのためにトリックをするかもしれません。

これについてはこちらをお読みください。の使用法を理解できるMVVMの基本に関するJoshSmithの記事INotifyPropertyChanged。WPF環境にありますが、WinFormsでも使用できます。

于 2012-08-28T12:42:13.037 に答える
3

この種の問題を解決するために、パブリッシュ/サブスクライブパターンパターンを使用することに成功しました。誰かが何かを変更するときはいつでも、誰かが知りたいと思うかもしれませんが、あなたは「ObjectWasModified」イベント、または「NewUserAdded」などが必要な場合はより具体的な何かを発生させます...そして、すべてのサブシステムまたは他のものはいつそれを知る必要があります発生すると、そのタイプのイベントをサブスクライブします。テンプレートパラメータをイベントObjectWasModifiedまたは追加の条件に追加して、各システムが本当に関心のあるイベントのみを受信するようにすることができます。

于 2012-07-09T03:18:37.330 に答える
3

.NETに組み込まれているイベントモデルを使ってみませんか?質問を正しく理解していませんか?あなたの質問は、これが多くの「オーバーヘッド」を追加すると思うことを示しています(パフォーマンスを意味するのか開発を意味するのかは明確ではありません)が、このソリューションはパフォーマンスの観点から非常に軽量です。

class YourModel
{
    //---- event class can contain data elements to update listeners
    public class DataChangedEventArgs : EventArgs
    {
        ...
    }

    //---- this is what the client callback need to look like
    public delegate void DataChangedDelegate(object oSender, DataChangedEventArgs args);

    //---- public event that clients subscribe to
    public event DataChangedDelegate evtDataChanged;

    //---- any changes in YourModel invoke this method to notify clients
    protected void OnChanged(DataChangedEventArgs args)
    {
        if (evtDataChanged != null)
            evtDataChanged(this, args);
    }

    //---- method(s) in your Model that change internal data
    public void ImaDataChanger(...) 
    {
        //---- stuff that changes the data

        OnChanged(args);    //-- notify clients
    }
}

class UserSelectionView
{
    //---- the event callback
    public void DataChangedHandler(object oSender, YourModel.DataChangedEventArgs args)
    {
        //---- process update or refresh data
        //---- UI updates will have to be marshalled to the UI thread
    }

    //---- sign up for events
    public void Subscribe(YourModel model)
    {
        model.evtDataChanged += new YourModel.DataChangedDelegate(DataChangedHandler);
    }
}

追加のイベントを定義するか、DataChangedEventArgsにデータメンバーを追加して、データ変更のタイプに関する情報を提供するオプションがあります。

また、以下のコメントに示されているように、ビューを別のコンピューターまたは同じコンピューター上の別のプロセスに配置する必要がある場合は、.NET Remotingを使用して、コードをほとんど変更せずにこれを実現できます。

于 2012-08-29T06:34:36.873 に答える