1

複数の画面があり、WCF Web サービスと通信するアプリケーションがあります。お気に入りの IoC コンテナーには SimpleInjector を使用し、WPF を使用した MMVM には Caliburn Micro を使用しています。

ITransportClientWeb サービスへの接続を制御し、メッセージを送受信する別のクラス実装があります。

アプリケーションには次の状態があります。

  1. アプリケーションの起動と初期化。
  2. ログインフォームを表示します。
  3. ログインフォームは でチャットサーバーへの接続を行いますITransportClient.Login(username, password)
  4. ログインに成功すると、新しい MainWindow ビューが表示されます。ログインに失敗した場合は、ユーザーに再度資格情報を求めるプロンプトを表示します。
  5. ログインすると、MainWindow は WCF サービスとの間で送受信されるメッセージを制御します。
  6. サーバーとの接続が失われた場合 ( で通知ITransportClientCallback.OnTransportDisconnected)、またはユーザーがログアウトをクリックした場合、ログイン フォームが再度表示されます。

私が利用できるテクノロジと、これが私の最初の MVVM プロジェクトであるため、次のアーキテクチャと設計に関する質問があります。

  1. 別のログイン画面を表示し、接続時にメイン画面を表示し、接続が失われたときにログイン画面に戻るには、どのデザイン パターンを使用すればよいですか?
  2. チャット アプリケーションの接続状態を制御するのは誰で、このコードはどこに配置しますか? この状態はブートストラップ クラスに含まれますか?
  3. ITransportClient を永続化インスタンス スコープとして登録し、それを必要とする ViewModel (つまり、ログイン フォームとメイン ウィンドウ フォームの両方) に挿入することで、必要に応じて複数のフォーム コントロールを使用できますか?

インターフェイスは次のITransportClientとおりです。

public interface ITransportClientCallback
{
    string OnReceivedMessage();
    void OnTransportDisconnected();
}

// transport interface that client calls
public interface ITransportClient
{
    bool SendLogin(string username, string password);
    void SendLogout();
    void SendMessage();
    void RegisterCallback(ITransportClientCallback applicationHostCallback);
}

SimpleInjector を使用した Caliburn.Micro ブートストラップ コードと共に:

public class SimpleInjectorBootstrapper : Caliburn.Micro.Bootstrapper
{
    private Container container;

    protected override void Configure()
    {
        this.container = new Container();
        this.container.Register<IWindowManager, WindowManager>();
        this.container.Register<IEventAggregator, EventAggregator>();
        this.container.Register<IAppViewModel, AppViewModel>();
        this.container.RegisterSingle<ITransportClient, Transport.WCF.TransportClient>();
    }

    protected override object GetInstance(Type serviceType, string key)
    {
        return this.container.GetInstance(serviceType);
    }

    protected override IEnumerable<object> GetAllInstances(Type serviceType)
    {
        return this.container.GetAllInstances(serviceType);
    }

    protected override void OnStartup(object sender, System.Windows.StartupEventArgs e)
    {
        base.OnStartup(sender, e);
        var appViewModel = this.container.GetInstance<IAppViewModel>();
        var windowManager = this.container.GetInstance<IWindowManager>();
        windowManager.ShowWindow(appViewModel);
    }
}
4

1 に答える 1

3

別のログイン画面を表示し、接続時にメイン画面を表示し、接続が失われたときにログイン画面に戻るように制御するには、どのデザインパターンを使用する必要がありますか?

多くの場合、MVVMプロジェクトには「メディエーター」または「メッセンジャー」が付属しています。すべてのビューモデルは、メッセージをサブスクライブおよび公開することにより、このメカニズムを介して相互に対話できます。すべてのVMは「UserLoggedOutMessage」にサブスクライブし、必要な応答を実行します(つまり、視覚的な状態を読み取り専用に変更するか、何も表示しません)。別のブートストラッパーは、ユーザーをログイン画面に「リダイレクト」することもできます。

チャットアプリケーションの接続状態を誰が制御する必要があり、このコードはどこに配置されますか?この状態はブートストラッパークラスに属しますか?

1つのアプローチは、アプリの状態を抽象化することです。これは、asp.netのHTTPContext.Current変数と同等です。ステートマシンとして機能する対応するLogin()、Logout()、SendMessage()メソッドを持つCurrentState読み取り専用プロパティを持つSessionオブジェクトを持つことができます。すべてのビューモデルは、アプリの状態が変化するとすぐにイベントをサブスクライブします-再びメディエーターを介して。Sessionオブジェクトは、ブートストラッパー上の静的変数、またはIoCを介してすべてのVMに注入されるシングルトンにすることができます。

ITransportClientを永続インスタンススコープとして登録し、それを必要とするViewModel(つまり、ログインフォームとメインウィンドウフォームの両方)に挿入することで、必要に応じて複数のフォームを制御できますか?

それは間違いなくアイデアです。ほとんどのMVVMプロジェクトでは、依存関係の単一インスタンスをVMに注入する必要があります。これにより、より効率的なメモリの使用が可能になり、(手続き型の不変のトランザクションスクリプトとは対照的に)クリーンなオブジェクト指向モデルも可能になります。

そうは言っても、これが「アプリケーションの状態」をチェックする試みである場合、抽象化のレベルをIApplicationStateMachineやIUserSessionなどのより高いレベルに変更します。このように、1つのアプリケーションインスタンスで複数のユーザーをサポートしたい場合、理論的にはIUserSessionオブジェクトの複数のインスタンスを持つことができます。

于 2012-11-25T11:56:46.940 に答える