【问题标题】:MVVMLight and platform specific service implementationsMVVMLight 和平台特定的服务实现
【发布时间】:2015-05-25 21:37:28
【问题描述】:

我有什么

使用 MVVMLight,我有一些在可移植项目中声明的服务接口和在 Windows Phone 项目(WP8.1 SL)中的相应实现。要注册实现,我在 App 类的 Application_Launching 方法中使用 SimpleIoc.Default.Register

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);

        ...
    }

    ...
}

视图模型定位器位于可移植项目中,并将所有视图模型注册到静态构造函数中的 IOC 容器,正如文档所说。

static ViewModelLocator()
{
    ...

    SimpleIoc.Default.Register<TagColorViewModel>();

    ...
}

TagColorViewModel 是这些型号之一。它在显示相应视图之前收到一条消息。例如,当一个标签被点击改变它的颜色时,然后MessengerInstance.Send被使用,然后导航服务被用来导航到标签颜色改变视图。

// TagViewModel
private void ChangeColor()
{
    MessengerInstance.Send(Tag, TagColorViewModel.MessengerToken.SetTag);
    _navigationService.Navigate("/UI/Tagging/TagColor.xaml");
}

这个消息接收者在构造函数中注册。

// TagColorViewModel
[PreferredConstructor]
public TagColorViewModel(INavigationService navigationService)
{
    ...

    // Messages
    MessengerInstance.Register<Tag>(this, MessengerToken.SetTag, SetTag);
}

实际问题

因为视图模型是在第一次通过其相应视图使用之前在 MVVMLight 中创建的,所以TagColorViewModel 没有收到该消息(仅仅是因为还没有该 VM 的实例)。

一个可能的解决方案是在注册视图模型时使用true 作为参数。

SimpleIoc.Default.Register<TagColorViewModel>(true);

不幸的是,这不起作用。原因是,从上面的构造函数中可以看出,TagColorViewModel 依赖于INavigationService。这又在 Application_Launching 方法中注册,该方法是在调用视图模型定位器的静态构造函数之后。结果是 SimpleIoc 无法创建 TagColorViewModel 的实例,因为没有已知的 INavigationService 接口或实现。

实际问题

我该如何解决这个问题?换句话说:如何在 MVVMLights SimpleIoc 中注册特定于平台的服务,以便在注册期间让它创建视图模型的实例?

Xamarin 似乎使用装饰器来解决此类问题,但我不知道 MVVMLight 中有任何类似的构造。

Xamarin.Forms.Dependency(typeof(PopupService))

当前的解决方法

我当前的解决方法是在注册所有平台特定服务后立即获取一个以后不再使用的实例。它有效,但我认为这不是正确的解决方案。

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>();

    ...
}

【问题讨论】:

    标签: c# mvvm-light


    【解决方案1】:

    结合使用 Xamarin 的依赖服务和 MVVMLight。 MVVMLight 的 Register 方法有一个重载,您可以编写自己的函数来生成实例。

    像这样将所有服务注册放回 ViewModelLocator:

    SimpleIoc.Default.Register<Service.INavigationService>(() => {
         return DependencyService.Get<Service.INavigationService>();
    });
    

    然后将适当的程序集属性放在特定于平台的服务实现中......

    [assembly: Xamarin.Forms.Dependency(typeof(NavigationService))]
    

    【讨论】:

      【解决方案2】:

      一种方法可能是在应用构建期间而不是在Application_Launching 中执行特定于平台的服务注册。这将确保您的所有服务尽早注册。唯一需要注意的是确保它们在调用 ServiceLocator.SetLocatorProvider 之后发生。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-11-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-13
        相关资源
        最近更新 更多