假设我有三个带有此文件夹和命名空间结构的项目:
MyApp.Core: Plugins/Settings/ISettings.cs Plugins/Settings/PluginLoader.cs MyApp.Droid: Plugins/Settings/Settings.cs Plugins/Settings/Plugin.cs Bootstrap/SettingsPluginBootstrap.cs MyApp.Touch: Plugins/Settings/Settings.cs Plugins/Settings/Plugin.cs Bootstrap/SettingsPluginBootstrap.cs
iOS项目的工作方式与预期一致,并且可以毫无问题地找到插件.
另一方面,Droid项目失败,但有异常:无法加载文件或程序集“MyApp.Plugins.Settings.Droid.dll”或其依赖项之一.
如果我将PluginLoader的命名空间从MyApp.Core.Plugins.Settings更改为简单的MyApp,则该插件可以正常工作;我想它会查找MyApp.dll并找到它.但是,如果我的应用程序中有多个插件,它们应该都有自己的命名空间,它们不能都在MyApp命名空间中.
目前我发现的唯一解决方法是为我创建的每个插件创建一个单独的项目,尽管这感觉有点不必要.
为什么PluginLoader坚持在Android上查找< PluginLoader命名空间> .Droid.dll文件,当iOS上的PluginLoader发现插件没有任何问题?
解决方法
通过使用命名空间和程序集的共享模式,以及几个辅助类(Plugin和PluginLoader),插件提供了一种共享和重用可移植本机代码组件的方法.
iOS(和Mac)使用略有不同的插件加载方案的原因是因为MonoTouch的AoT编译器不允许动态Assembly.Load加载.
因为这个iOS必须使用不同类型的PluginManager和不同类型的Bootstrap类到其他平台.在https://github.com/MvvmCross/MvvmCross/wiki/MvvmCross-plugins#how-plugins-are-loaded中的“如何加载插件”中有更多信息
如果你想将Loader类型插件注册表添加到Android和iOS,那么我认为你可以在自定义PluginManager类中执行此操作,然后可以在安装过程中使用覆盖受保护的覆盖IMvxPluginManager CreatePluginManager()来创建它.
就像是:
public class MyPluginManager : MvxFilePluginManager,IMvxLoaderPluginManager { private readonly Dictionary<string,Func<IMvxPlugin>> _finders = new Dictionary<string,Func<IMvxPlugin>>(); public MyPluginManager(string platformDllPostfix,string assemblyExtension = "") : base(platformDllPostfix,assemblyExtension) { } public IDictionary<string,Func<IMvxPlugin>> Finders { get { return _finders; } } protected override IMvxPlugin FindPlugin(Type toLoad) { var pluginName = toLoad.Namespace; if (string.IsNullOrEmpty(pluginName)) { throw new MvxException("Invalid plugin type {0}",toLoad); } Func<IMvxPlugin> finder; if (_finders.TryGetValue(pluginName,out finder)) { return finder(); } return base.FindPlugin(toLoad); } }
使用以下命令在安装程序中初始
protected override IMvxPluginManager CreatePluginManager() { return new MyPluginManager(".Droid",".dll"); }
然后你需要确保基于加载器的插件使用基于MvxLoaderPluginBootstrapAction而不是MvxPluginBootstrapAction的引导类
作为另一种选择,如果你不想单独重用你的插件 – 如果你不想发送大量单独的插件程序集 – 那么你可以将所有的接口和实现放在一个单独的程序集中 – 然后它们可以共享一个Bootstrap,它们之间的插件和PluginLoader.
作为最后的替代方案,为了满足您的自定义需求,您始终可以考虑使用自己的自定义引导类 – 标准安装程序将在您的UI程序集中创建并运行任何可构造的类,以实现IMvxBootstrapAction – 因此您可以将SettingsPluginBootstrap替换为一些自定义的Run操作,适合您的应用需求.
public class SettingsBootstrapAction : IMvxBootstrapAction { public void Run() { // my stuff here } }