(WPF / MVVM)IService和ViewModel有什么不同?

时间:2016-08-31 16:37:10

标签: c# wpf mvvm service interface

我想在 ViewModel 中使用 SaveFileDialog ,但由于从 ViewModel 绑定到View不正确,我搜索了方法要做到这一点。但我发现一些答案没有完全区分查看形式 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 中设置了实例

IDialog iDialog = new IDialog();

所以我想知道,这种方法与直接从 ViewModel 调用 MessageBox SaveFileDialog 之间的差异是什么?

注意: 我也发现了一些可以使用上述服务的内容,但是按照以下方式实现:

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

但我不知道如何将 IOService 作为参数发送到 ExportViewModel (因为我们无法从实例创建实例 界面!)

2 个答案:

答案 0 :(得分:3)

您不应直接从VM弹出对话框以实现自动化测试。

如果您调用MessageBox.Show(),您的测试将一直停滞,直到有人关闭对话框。

相反,如果你使用“IMessageBox”进行单元测试,你可以注入一个实际上不显示对话框的实现,而是返回一个特定的值(结果)。

答案 1 :(得分:0)

它是一种抽象,用于将UI问题与视图模型分开,并允许您在单元测试中拦截这些调用。拦截这些调用允许您在测试期间阻止显示对话框(这将阻止测试的执行,而不是好)并验证视图模型是否按预期运行。

将其称为“服务”或调用抽象“IService”没有什么特别之处。这只是对共同模式的暗示

  • 我需要做点什么
  • 我不能自己做。
  • 我会找到一份可以聘请的服务
  • 我找到了一项可以为我做这件事的服务
  • 此服务将为我做这件事

你也可以称它为“IDontTouchUIStuffInMuhViewModel”,但那不是那么优雅。

通过在视图模型中提供接口的实现,可以在运行时轻松解决第二个问题。您的视图模型不应该关心它是如何实现的(polymorphism),因此您可以在运行时传递合法的实现,并在测试期间传递假的实现。

您也可以使用Dependency InjectionInversion of Control来完成此操作。通过使用Unity等库来实例化视图模型,将根据您配置容器的方式自动提供所有依赖项。