首先,让我们看看 ViewModelLocator 的作用以及我们使用它的原因:
ViewModelLocator 在我们的 App.xaml 页面上被声明为一个对象,并且是一个应用程序单例。我们将拥有一个,并且只有其中一个可供应用程序运行时使用。
ViewModelLocator 是 MVVM Light 中所有 ViewModel 的来源。对于每个 ViewModel,我们将在 ViewModelLocator 上拥有一个属性,该属性允许我们获取 View 的 ViewModel。此代码如下所示:
public class ViewModelLocator
{
public MainPageViewModel MainPage
{
get { return new MainPageViewModel(); }
}
}
这是我的 App.xaml 的一部分:
<Application.Resources>
<vm:ViewModelLocator
x:Key="ViewModelLocator" />
</Application.Resources>
这是来自 View.xaml 的一部分
DataContext="{Binding MainPage, Source={StaticResource ViewModelLocator}}"
到目前为止一切顺利。要回答您的第一个问题,您是否必须在 MVVM Light 中使用 Ioc?不。没有必要,因为您的视图模型将提供给由 ViewModelLocator 完全构建和实例化的视图。
现在,进入第二个问题:IoC 的目的是什么?
IoC 旨在让您执行以下操作:
使用 Mvvm Light,您可以像这样执行上述操作:
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}
SimpleIoc.Default.Register<MainViewModel>();
}
public MainViewModel Main
{
get { return SimpleIoc.Default.GetInstance<MainViewModel>(); }
}
}
public class MainViewModel
{
public ObservableCollection<Foo> Foos { get; set; }
public MainViewModel(IDataService dataService)
{
_dataService=dataService;
Foos=_dataService.GetFoos();
}
}
当我调用时解析 MainViewModel 时
SimpleIoc.Default.GetInstance<MainViewModel>()
内部发生的是 SimpleIoc 检查 MainViewModel 是否有任何依赖项(其构造函数中的参数)。然后,它会尝试通过查看已注册的接口来解析这些参数。它以递归方式执行此操作,因此如果 DataService 具有依赖关系,它也会在实例化时被实例化并传递给 DataService 构造函数。
我为什么要做所有这些工作?
- 让您的课程易于单元测试
- 使您的代码界面驱动。这意味着您引用的是接口而不是具体的类
- 使您的代码松散耦合。这意味着某人可以更改接口的实现,而使用该接口的类不需要重新编码。
- 以自动方式解决您的类依赖关系。
- 在 MVVM Light 中,您会看到它可以判断何时在设计模式下运行 (
ViewModelBase.IsInDesignModeStatic),这意味着您可以创建设计时服务来提供您的视图模型数据,以便您在 Visual Studio 中的视图包含实际数据。