Ich entwickle eine C#/WPF/MVVM/UWP-App, die eine ViewModelLocator verwendet, die wie folgt aussieht:sicher, dass eine statische Klasse vor den anderen
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>();
}
}
Ich habe eine andere Klasse, eine ViewLocator, für die Navigation der wie folgt aussieht:
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>();
}
}
Bevor wurden beide Klassen in ViewModelLocator kombiniert, jedoch dachte ich, dass der ViewModelLocator als Teil der „Viewmodels-Side-of-Dinge“ soll die Ansichten nicht bewusst sein und Es sind Typen, weshalb ich diesen Code in zwei Klassen umstrukturiert habe.
Mein MainPageView dann eine Taste hat, die einen Navigationsbefehl in den MainPageView.cs löst
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);
}
}
Für Vollständigkeit, hier ist mein App.xaml
<Application
...>
<Application.Resources>
<v:ViewLocator x:Key="ViewLocator" />
<vm:ViewModelLocator x:Key="ViewModelLocator" />
</Application.Resources>
Nun, was passiert ist das: wenn ich nicht die DEBUG LINE in ViewModelLocator habe, an dem Punkt, an dem MainPage sein ViewModel vom ViewModelLocator anfordert, hat der Konstruktor von ViewLocator wurde noch nicht aufgerufen und return ServiceLocator.Current.GetInstance<MainPageViewModel>();
löst eine Ausnahme aus. Wenn ich die DEBUG-LINE einschließe, erzwingt das, dass der ViewLocator-Konstruktor zuerst ausgeführt wird, und alles funktioniert gut.
Wie kann ich dieses Verhalten ohne diese seltsame Debug-Zeile erreichen?
Ich werde nur hier verlassen [ist ServiceLocator Anti-Muster] (http://stackoverflow.com/questions/22795459/is-servicelocator-anti-pattern) – Liam
TL; DR Sie sollten wirklich Dependency verwenden Injektion nicht Service Locator Muster. Wenn man von vorne anfängt, ist es normalerweise ein viel besseres und einfacheres Muster zu verstehen. – Liam
@Liam Ich bin kein Fan von IoC Containern oder ServiceLocator oder wie immer man es nennen möchte. Ich habe nur untersucht, wie man VM und V richtig trennt, und dies ist der einzige Arbeitsansatz, der mich bisher zufriedenstellt. Ich bin jedoch sehr offen für die Verwendung von DI - wenn Sie mir bitte einen Referenzcode zeigen könnten, der es richtig verwendet. – Xaser