2016-08-31 4 views
1

私は私のViewModel SaveFileDialogを使用していた、しかし、それはViewModelにから見ると結合を修正していないことから、私はそれを行うための方法を探しました。(WPF/MVVM)IServiceとViewModelの違いは何ですか?

public interface IOService 
{ 
    void IMessageBox(string Message); 
    string ISaveFileDialog(string DefaultPath); 
} 
public class IDialog : IOService 
{ 
    public void IMessageBox(string Message) 
    { 
     System.Windows.MessageBox.Show(Message); 
    } 

    public string ISaveFileDialog(string DefaultPath) 
    { 
     System.Windows.Forms.SaveFileDialog dg = new SaveFileDialog 
     { 
      InitialDirectory = DefaultPath, 
      Filter = "PDF files (*.pdf) | *.pdf" 
     }; 
     dg.ShowDialog(); 
     if (dg.FileName == null) 
      dg.FileName = string.Empty; 
     return dg.FileName; 
    } 
} 

は、彼らはそれがからビューを分離する使用して、これはサービスである、と言ったと。しかし、私はこのようなビューフォームのViewModel完全に分離しないいくつかの答えを見つけましたViewModel。しかし、我々はのViewModelにこのからインスタンスを作成している:

IDialog iDialog = new IDialog(); 

だから私は知りたい、この方法と、直接のViewModelからメッセージボックスまたはSaveFileDialogを呼び出す間diffrenceは何ですか?

注:はまた、私は、私は上記のようなサービスを利用することができると言いました何かを見つける、しかし、このようにそれを実装:

public class ExportViewModel : BaseViewModel 
{ 
    IOService _IOService; 
    public ExportViewModel(IOService ioservice) 
    { 
     _IOService = ioservice; 
     . 
     . 
    } 
} 

しかし、私はIOServiceの送る方法がわかりませんExportViewModelインスタンスのインスタンスを作成できないため、

答えて

3

自動テストのために、VMから直接ダイアログをポップアップしないでください。

MessageBox.Show()を呼び出すと、ユーザーがダイアログを閉じるまでテストが停止します。

単体テストのために "IMessageBox"を使用すると、実際にダイアログを表示せず、むしろ特定の値(結果)を返す実装を挿入できます。

+0

これはテストの問題であり、VMからVを分離するものではありません。だから私は単体テストを使わないので、MessageBox.Show()を使ってMVVMに違反しないでください。 – Mostafa

+0

@Mostafaユニットテストは1つのケースです。もう一つのケースは、今日はMessageBoxを使いたい、明日はMyCoolDialogを使いたいということなので、大規模な検索と置換の代わりに実装クラスを取り替えるだけです。 MVVMを使用している場合は、すでにDIを使用しているはずです。単純なインターフェースを定義し、実装にMessageBoxを貼り付けてください。それはあなたの将来を突き詰めるでしょう。 – SledgeHammer

+0

ありがとう、しかし、私はどのようにインターフェイスがそれを行うことができるか分からない!私の質問の2番目の部分はまさにこれでした。インターフェイスには初期化メソッドがいくつか含まれています。実装ではありません。したがって、このインターフェイスを使用する各クラスでは、メソッドの本体を定義する必要があります。それはまったく役に立ちません。私はちょうどクラスを書くことができます(上記のIDialogのように)、すでにメソッドを使っています! – Mostafa

0

これは、UIの問題をビューモデルから切り離し、単体テスト内でこれらの呼び出しを代行する手段を提供するための抽象です。これらの呼び出しをインターセプトすることで、テスト中にダイアログを表示しないようにすることができます(テストの実行を妨げる、良いことではありません)。

「サービス」と呼ぶか、抽象化「IService」を呼び出すことについて特別なことは何もありません。それは

  • は、私が何かを行う必要がある一般的なパターンにだけ言及だ
  • 私はそれを自分で行うことはできません
  • 私はそれが
  • 私が見つけ行うに雇うことができるサービスを見つけることができます
  • 私のためにこれを行うことができますサービスは
  • このサービスは私

あなただけのようにも「IDontTouchUIStuffInMuhViewModel」それを呼び出すことができますのためにそれを行うだろうが、それはエレガントではありません。

ビューモデルにの実装を提供することで、2番目の問題は実行時に簡単に解決されます。あなたのビューモデルは実装方法(polymorphism)に気を付けるべきではないので、実行時に正当な実装を渡し、テスト中に偽のものを渡すことができます。

Dependency InjectionまたはInversion of Controlを使用してこれを行うこともできます。 Unityなどのライブラリを使用してビューモデルをインスタンス化すると、コンテナの設定に基づいてすべての依存関係が自動的に提供されます。

+0

このサービスやインターフェイスはすべて単体テストに使用されていますか?だから、これで、私が前に言ったように、VM内でMessageBox.Show()を呼び出すことができました! – Mostafa

+0

@Mostafaいいえ...あなたのVMは、ダイアログ、コントロール、または他のUI要素で何もしないでください。もしそうなら、あなたはMVVMの原則に違反しています。 Willが言っていることの全体的なポイントは、VMが実際にUIオブジェクトに依存することを望まないということです。インターフェイスをctorに渡すことは、それらを分離するためのツールです。このように考えてみましょう。ファイル保存ダイアログではなく、画面の下に独自のカスタムファイルセレクタを表示するためにUIを再作成する必要がある場合、それを行うことはできますか?それを正しく行うと、新しいUIはインターフェイスに接続され、魔法のように動作します! –

+0

@Lynn私はDIとIoCをちょうど今読んでいました。そして理解しているのは、この質問はそれらに依存しています。私は多くの文献から読んだが、それでもそれは得られない!私はMVVMを使ってアプリケーションを書いていましたが、最終段階に入っていますが、私はすべてのプログラムでDIやIoCを使用しませんでした。だから私はあなたが今言ったようなものをどうやってやれるかは実際にはわかりません。 – Mostafa

関連する問題