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)
或类似的东西进行一些黑客攻击。
你提到:
我无法在构造函数中注入数据源,必须按照
// Used now
.
当你尝试这个时,你看到了什么? 抛出什么异常? 为什么以下方法不起作用?
Mains = new ObservableCollection<MainViewModel>(
_service.GetAll().Select(model => new MainViewModel(model, _service))
);
我认为如果您不使用服务定位器可能会有所帮助,这似乎是您目标的反模式。 使用 DI 容器时,最好在应用程序启动或 Web 请求(对于 Web 应用(时创建整个对象图。 但在这里,您使用 new 关键字来创建 MainViewModel。
请参阅此帖子。