MVVM Light 注入带有参数的数据服务

本文关键字:数据 服务 参数 Light 注入 MVVM | 更新日期: 2023-09-27 18:34:47

我的ExampleViewModel有一个参数(模型(,它需要正常运行。我还有一个ExampleViewModel的列表变体,它只包含一个ObservableCollection<ExampleViewModel>并有一些包装方法。

当我尝试将依赖注入与 MVVM Light 一起使用时,该问题会显示出来。让我用一些代码解释这个场景。

默认视图模型定位器:

public class ViewModelLocator {
    public ViewModelLocator() {
        ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
        if (ViewModelBase.IsInDesignModeStatic) {
            SimpleIoc.Default.Register<IDataService, DesignDataService>();
        } else {
            SimpleIoc.Default.Register<IDataService, DataService>();
        }
        SimpleIoc.Default.Register<MainViewModel>();
    }
    public MainViewModel Main {
        get {
            return ServiceLocator.Current.GetInstance<MainViewModel>();
        }
    }
    public static void Cleanup() {}
}

简单主视图模型:

public class MainViewModel : ViewModelBase {
    private IDataService _service;
    private MainModel _model;
    // Goal. I think?
    public MainViewModel(IDataService service, MainModel model) {
        _service = service;
        _model = model;
    }
    // Used now
    public MainViewModel(MainModel model) {
        _service = ServiceLocator.Current.GetInstance<IDataService>();
        _model = model;
    }
}

ListMainViewModel填充它的列表是这样的:

Mains = new ObservableCollection<MainViewModel>(
    _service.GetAll().Select(model => new MainViewModel(model))
);

由于在ListMainViewModel中创建列表,我无法在构造函数中注入数据源,必须使用它,如 // Used now 所示。这很好,但是当我尝试单元测试时,可能会出现问题,正如您可能想象的那样。

我目前使用这样的单元测试:

public void ListMainViewModel_DoSomething_Success() {
    // Arrange
    var mock = new Mock<IDataService>();
    mock.Setup(m => m.Create(new MainModel { Naam = "Create" }));
    mock.Setup(m => m.Update(new MainModel { Naam = "Update" }));
    var listMainViewModel = new ListMainViewModel(mock.Object);
    var selected = new MainModel() { Prop = "Test" };
    listMainViewModel.SelectedMainViewModel = new MainViewModel(selected);
    // Act
    listMainViewModel.DoSomething();
    // Assert
    mock.Verify(x => listMainViewModel.DoSomething(), Times.Exactly(1));
}

注意:不确定单元测试是否正确。但是创建SelectedMainViewModel时出现问题,因为它不会获取DataService

现在我有两个选择(我认为(,我可以在 MainViewModel 中使 MainModel 成为可选,这不应该是可能的,并且构造器注入了 IDataService。或者我可以发现一种方法,使_service可以被MainViewModel找到。

有什么优雅的方法可以解决这个问题吗?因为我有一种感觉,我必须使用if (InDesignMode)或类似的东西进行一些黑客攻击。

MVVM Light 注入带有参数的数据服务

你提到:

我无法在构造函数中注入数据源,必须按照// Used now .

当你尝试这个时,你看到了什么? 抛出什么异常? 为什么以下方法不起作用?

Mains = new ObservableCollection<MainViewModel>(
    _service.GetAll().Select(model => new MainViewModel(model, _service))
);

我认为如果您不使用服务定位器可能会有所帮助,这似乎是您目标的反模式。 使用 DI 容器时,最好在应用程序启动或 Web 请求(对于 Web 应用(时创建整个对象图。 但在这里,您使用 new 关键字来创建 MainViewModel。

请参阅此帖子。