如何使用 mvvmcross 插件,例如文件插件

How to use an mvvmcross plugin such as the file plugin

我正在使用 mvvmcross 版本 6.4.1 为 IOS、Android 和 WPF 开发应用程序。 我到处搜索我要使用的插件。似乎没有代码示例。文档说要在我的核心和 ui 应用程序项目中安装 nuget。我做到了。在我可以使用该插件之前是否需要完成任何特殊的 IOC registration/setup/or 加载,我该如何使用该插件?它们是被注入到构造函数中还是我必须手动将它们从 IOC 容器中拉出或 new () 它们。

我已经为文件插件安装了 nuget 到我的 WPF UI 和核心项目中。我将 IMvxFileStore 添加到我的一个核心项目的服务构造函数中,认为它会自动添加到 DI 容器中,但它似乎没有被注入。

namespace My.Core.Project.Services
{
   public class SomeService : ISomeService
   {
      private IMvxFileStore mvxFileStore;
      public SomeService(IMvxFileStore mvxFileStore)
      {
         this.mvxFileStore = mvxFileStore;
      }

      public string SomeMethod(string somePath)
      {
          mvxFileStore.TryReadTextFile(somePath, out string content);

          return content;
      }
   }
}

App.xaml.cs

using MvvmCross.Core;
using MvvmCross.Platforms.Wpf.Views;
...

public partial class App : MvxApplicatin
{
   protected override void RegisterSetup()
   {
      this.RegisterSetupType<Setup<Core.App>>();
   }
}

App.cs

using MvvmCross;
using MvvmCross.ViewModels;
using My.Core.Project.Services;

public class App: MvxApplication
{
  public override void Initialize()
  {
    Mvx.IocProvider.RegisterType<ISomeService, SomeService>();
    RegisterCustomAppStart<AppStart>();
  }
}

AppStart.cs

using MvvmCross.Exceptions;
using MvvmCross.Navigation;
using MvvmCross.ViewModels;
using My.Core.Project.ViewModels;
using System;
using System.Threading.Tasks;

....

public class AppStart : MvxAppStart
{
  public AppStart(IMvxApplication application, IMvxNavigationService navigationService) : base(application, navigationService)
  {}

  public override Task NavigateToFirstViewModel(object hint = null)
  {
     try {
         return NavigationService.Navigate<FirstPageViewModel>();

     } catch {
         throw e.MvxWrap("Some error message {0}", typeof(FirstPageViewModel).Name);
     }
  }

}

Setup.cs 在 WPF 项目中

using MvvmCross;
using MvvmCross.Base;
using MvvmCross.Platforms.Wpf.Core;
using MvvmCross.Plugin.File;
using MvvmCross.Plugin.Json;
using MvvmCross.ViewModels;
using My.Wpf.Project.Services;
...

public class Setup<T> : MvxWpfSetup
{
    public Setup() : base() {}

    protected override IMvxApplication CreateApp()
    {
        return new Core.App();
    }

    protected override void InitializeFirstChange()
    {
        base.InitializeFirstChange();
        Mvx.IocProvider.RegisterType<ISomeWpfSpecificService>(() => new SomeWpfSpecificService());

    }

     protected override void InitializeLastChange()
     {
        base.InitializeLastChange();
     }
}

我期待我的服务加载,但我收到了错误消息 MvxIoCResolveException:无法为参数 mvxJsonConverter of imvxJsonConverter

解析参数

注意:对于文件和 Json 插件,我收到相同的错误消息,在构造函数中首先列出的插件在应用程序尝试加载时收到错误消息。

我是否正确使用或加载了插件?

更新: 我在 UI Setup.cs 中手动注册了插件,它正在工作,但我不确定这是否是正确的方法做吧。

WPFUI 项目Setup.cs

using MvvmCross;
using MvvmCross.Base;
using MvvmCross.Platforms.Wpf.Core;
using MvvmCross.Plugin.File;
using MvvmCross.Plugin.Json;
using MvvmCross.ViewModels;
using My.Wpf.Project.Services;
...

public class Setup<T> : MvxWpfSetup
{
    public Setup() : base() {}

    protected override IMvxApplication CreateApp()
    {
        return new Core.App();
    }

    protected override void InitializeFirstChange()
    {
        base.InitializeFirstChange();
        Mvx.IocProvider.RegisterType<ISomeWpfSpecificService>(() => new SomeWpfSpecificService());
        Mvx.IoCProvider.RegisterType<IMvxFileStore, MvxFileStoreBase>();
        Mvx.IoCProvider.RegisterType<IMvxJsonConverter, MvxJsonConverter>();

    }

     protected override void InitializeLastChange()
     {
        base.InitializeLastChange();
     }
}


是的,您正在正确使用插件,我认为目前您手动注册插件的解决方案是可行的。

问题的根源位于MvxSetup class。这个 class 包含方法 LoadPlugins 负责加载你的 UI 项目引用的 MvvmCross 插件。这就是 LoadPlugins 确定要加载的插件的方式:

  1. 获取所有已加载到应用程序域的执行上下文中的程序集。
  2. 在这些程序集中查找包含 MvxPluginAttribute.
  3. 的类型

现在问题出现在步骤 1 中。在 .NET Framework 项目中,默认情况下,您引用的程序集不会加载到执行上下文中,直到您在代码中实际使用它们。因此,如果您不在 UI 项目中使用 MvvmCross.Plugin.File 引用中的某些内容,它将不会加载到您的执行上下文中,也不会在第 1 步中找到,因此它不会由 LoadPlugins 注册。 (好读:when does a .NET assembly Dependency get loaded

我测试过的一种方法是这样做:

protected override void InitializeFirstChance()
{
    // Because a type of the MvvmCross.Plugin.File.Platforms.Wpf reference is
    // used here the assembly will now get loaded in the execution context
    var throwaway = typeof(Plugin);

    base.InitializeFirstChance();
}

使用上面的代码,您不必手动注册 Plugin

后来出现了pull request to fix this in the MvvmCross framework but this has been reverted,因为它在其他平台上引起了问题。

在其他平台上,插件程序集将在没有任何技巧的情况下加载到执行上下文中,所以我想说更新 MvvmCross 文档,说明您必须为 WPF 手动注册插件,这对将来的其他开发人员很有用。