我的ExampleViewModel
有一个需要正常运行的参数(模型)。我还有ExampleViewModel
的列表变体,它只包含ObservableCollection<ExampleViewModel>
并且有一些包装器方法。
当我尝试使用依赖注入MVVM Light时,问题显示出来了。让我用一些代码来解释这个场景。
默认ViewModelLocator:
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() {}
}
简单的MainViewModel:
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。或者我可以通过MainViewModel找到一种使_service可以找到的方法。
有没有优雅的方法来解决这个问题?因为我觉得我必须使用if (InDesignMode)
或类似的东西进行一些黑客攻击。
答案 0 :(得分:1)
你提到:
我无法在构造函数中注入数据源,必须按
// Used now
下所示使用它。
当你尝试这个时,你看到了什么?抛出什么异常?为什么以下工作没有?
Mains = new ObservableCollection<MainViewModel>(
_service.GetAll().Select(model => new MainViewModel(model, _service))
);
我认为如果你不再使用服务定位器可能会有所帮助,这似乎是你的目标的反模式。使用DI容器时,最好在应用程序启动或Web请求(对于Web应用程序)创建整个对象图。但是在这里您使用new关键字来创建MainViewModel。
请参阅此post。