使用MVVMLight,我有一些在可移植项目中声明的服务接口以及Windows Phone项目(WP8.1 SL)中的相应实现.注册我SimpleIoc.Default.Register在类中的Application_Launching方法中使用的实现App.
public partial class App : Application
{
...
private async void Application_Launching(object sender, LaunchingEventArgs e)
{
...
// add some platform specific services to the IOC container
SimpleIoc.Default.Register<INavigationService, NavigationServiceWP>(true);
SimpleIoc.Default.Register<ISettingsService, SettingsService>(true);
SimpleIoc.Default.Register<IThemeService, ThemeService>(true);
SimpleIoc.Default.Register<IGeofenceService, GeofenceService>(true);
SimpleIoc.Default.Register<IVersionService, TrialInformation>(true);
SimpleIoc.Default.Register<IPhoneService, PhoneServices>(true);
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
视图模型定位器位于可移植项目中,并在静态构造函数中将所有视图模型注册到IOC容器,就像文档所述.
static ViewModelLocator()
{
...
SimpleIoc.Default.Register<TagColorViewModel>();
...
}
Run Code Online (Sandbox Code Playgroud)
这TagColorViewModel是这些模型之一.它会在显示相应视图之前收到消息.例如,单击标签以更改其颜色然后MessengerInstance.Send使用,然后导航服务用于导航到标签颜色更改视图.
// TagViewModel
private void ChangeColor()
{
MessengerInstance.Send(Tag, TagColorViewModel.MessengerToken.SetTag);
_navigationService.Navigate("/UI/Tagging/TagColor.xaml");
}
Run Code Online (Sandbox Code Playgroud)
此消息接收器已在构造函数中注册.
// TagColorViewModel
[PreferredConstructor]
public TagColorViewModel(INavigationService navigationService)
{
...
// Messages
MessengerInstance.Register<Tag>(this, MessengerToken.SetTag, SetTag);
}
Run Code Online (Sandbox Code Playgroud)
因为视图模型是在MVVMLight中通过其相应的视图第一次使用之前创建的,所以消息不会被接收TagColorViewModel(因为还没有该VM的实例).
一种可能的解决方案是true在注册视图模型时用作参数.
SimpleIoc.Default.Register<TagColorViewModel>(true);
Run Code Online (Sandbox Code Playgroud)
遗憾的是,这不起作用.原因是,从上面的构造函数中可以看出,TagColorViewModel它具有依赖性INavigationService.这又在Application_Launching方法中注册,该方法在调用视图模型定位器的静态构造函数之后.结果是SimpleIoc无法创建实例,TagColorViewModel因为没有已知的INavigationService接口或实现.
我该如何解决这个问题?换句话说:如何在MVVMLights SimpleIoc中注册特定于平台的服务,以便我可以在注册期间创建视图模型的实例?
Xamarin似乎使用装饰器来解决这些问题,但我不知道MVVMLight中有任何类似的构造.
Xamarin.Forms.Dependency(typeof(PopupService))
Run Code Online (Sandbox Code Playgroud)
我目前的解决方法是在注册所有特定于平台的服务之后立即获取一个从未使用过的实例.它有效,但我不认为这是正确的解决方案.
private async void Application_Launching(object sender, LaunchingEventArgs e)
{
...
// add some platform specific services to the IOC container
SimpleIoc.Default.Register<INavigationService, NavigationServiceWP>(true);
...
var tcvm = SimpleIoc.Default.GetInstance<TagColorViewModel>();
...
}
Run Code Online (Sandbox Code Playgroud)
一种方法可能是在应用程序构建期间而不是在Application_Launching. 这将确保您的所有服务尽早注册。唯一的警告是确保它们在调用 后发生ServiceLocator.SetLocatorProvider。