【发布时间】:2016-09-08 14:33:24
【问题描述】:
我正在开发一个 C#/WPF/MVVM/UWP 应用程序,它使用如下所示的 ViewModelLocator:
public class ViewModelLocator
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
"CA1822:MarkMembersAsStatic",
Justification = "This non-static member is needed for data binding purposes.")]
public MainPageViewModel MainPage
{
get
{
return ServiceLocator.Current.GetInstance<MainPageViewModel>();
}
}
static ViewModelLocator()
{
// DEBUG LINE: var test = Views.ViewLocator.MainPageKey;
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IDataService, Design.DesignDataService>();
}
else
{
SimpleIoc.Default.Register<IDataService, DataService>();
}
SimpleIoc.Default.Register<MainPageViewModel>();
}
}
我有另一个类,一个 ViewLocator,用于导航目的,如下所示:
public class ViewLocator
{
public static readonly string MainPageKey = typeof(MainPage).Name;
public static readonly string WorkPageKey = typeof(WorkPage).Name;
static ViewLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
var navigationService = new NavigationService();
navigationService.Configure(MainPageKey, typeof(MainPage));
navigationService.Configure(WorkPageKey, typeof(WorkPage));
SimpleIoc.Default.Register<INavigationService>(() => navigationService);
SimpleIoc.Default.Register<IDialogService, DialogService>();
}
}
之前,这两个类都合并在 ViewModelLocator 中,但是我认为 ViewModelLocator 作为“ViewModels-Side-of-things”的一部分应该不知道视图及其类型,这就是我将该代码重构为两个的原因类。
然后我的 MainPageView 有一个按钮,它触发 MainPageView.cs 中的导航命令
public class MainPageViewModel : ViewModelBase
{
private INavigationService _navigationService;
public RelayCommand CreateNewImageCommand { get; private set; }
public MainPageViewModel(INavigationService navigationService)
{
_navigationService = navigationService;
CreateNewImageCommand = new RelayCommand(CreateNewImage, () => true);
}
public void CreateNewImage()
{
_navigationService.NavigateTo(Views.ViewLocator.WorkPageKey);
}
}
为了完整起见,这是我的 App.xaml
<Application
...>
<Application.Resources>
<v:ViewLocator x:Key="ViewLocator" />
<vm:ViewModelLocator x:Key="ViewModelLocator" />
</Application.Resources>
现在发生的情况是:如果我在 ViewModelLocator 中没有 DEBUG LINE,则在 MainPage 从 ViewModelLocator 请求其 ViewModel 时,尚未调用 ViewLocator 的构造函数,return ServiceLocator.Current.GetInstance<MainPageViewModel>(); 抛出异常.如果我包含 DEBUG LINE,这将强制 ViewLocator 构造函数首先运行,并且一切正常。
如果没有奇怪的调试行,我怎样才能实现这种行为?
【问题讨论】:
-
我将把它留在这里Is ServiceLocator anti-pattern
-
TL;DR 你真的应该使用依赖注入而不是服务定位器模式。通常,如果从头开始,这是一种更好、更容易理解的模式。
-
@Liam 我不是 IoC Containers 或 ServiceLocator 或任何你想称呼它的粉丝。只是我一直在研究如何正确分离VM和V,这是迄今为止唯一让我满意的工作方法。然而,我对使用 DI 持开放态度——如果你能告诉我一些正确使用它的参考代码。
-
大多数人使用IoC framework these days。例如Ninject
-
看看 Caliburn Micro;它将为您完成繁重的工作,您将获得 IoC ......是的,IoC 是要走的路。
标签: c# wpf mvvm static-classes