Как использовать плагины MvvmCross в Android без компиляции DLL?

StackOverflow https://stackoverflow.com//questions/20000008

  •  20-12-2019
  •  | 
  •  

Вопрос

У меня возникла проблема с использованием моих собственных плагинов MvvmCross в проекте Android, поскольку PluginLoader кажется, ожидает .Droid.dll точного пространства имен, в котором он находится.

Скажем, у меня есть три проекта с этой структурой папок и пространства имен:

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 терпит неудачу с исключением: Could not load file or assembly 'MyApp.Plugins.Settings.Droid.dll' or one of its dependencies.

Если я изменю пространство имен PluginLoader от MyApp.Core.Plugins.Settings просто MyApp, плагин работает;Я предполагаю, что он ищет MyApp.dll и находит его.Однако если в моем приложении несколько плагинов, каждый из них должен иметь свое собственное пространство имен, они не могут все находиться в MyApp пространство имен.

В настоящее время единственный обходной путь, который я нашел, — это создать отдельный проект для каждого создаваемого мной плагина, хотя это кажется немного ненужным.

Почему PluginLoader настаивать на поиске <PluginLoader namespace>.Droid.dll файл на Android, когда PluginLoader на iOS плагин находит без проблем?

Это было полезно?

Решение

Плагины MvvmCross предназначены для работы в качестве уровня сборки поверх IoC.

Используя общий шаблон для пространств имен и сборок, а также пару вспомогательных классов (Plugin и PluginLoader), плагины предоставляют возможность совместного использования и повторного использования переносимых компонентов собственного кода.

Причина, по которой iOS (и Mac) использует немного другую схему загрузки плагинов, заключается в том, что AoT-компилятор MonoTouch не допускает динамического Assembly.Load загрузка.

Из-за этого iOS приходится использовать другой тип PluginManager и другой тип Bootstrap класс на другие платформы.Дополнительную информацию об этом можно найти в разделе «Как загружаются плагины» в разделе «Как загружаются плагины». https://github.com/MvvmCross/MvvmCross/wiki/MvvmCross-plugins#how-plugins-are-loaded


Если вы хотите добавить Loader введите реестр плагинов для Android, а также для iOS, тогда я думаю, вы могли бы сделать это в пользовательском PluginManager класс и затем мог бы создать его во время установки, используя переопределение protected override 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");
    }

тогда вам нужно будет убедиться, что ваш loader Плагины на основе используют классы начальной загрузки, основанные на MvxLoaderPluginBootstrapAction и не MvxPluginBootstrapAction


В качестве альтернативы, если вы не заинтересованы в повторном использовании ваших плагинов по отдельности (если вы предпочитаете не поставлять множество отдельных сборок плагинов), вы можете поместить все свои интерфейсы и реализации в одну сборку, и тогда они смогут совместно использовать одну сборку. Bootstrap, Plugin и PluginLoader между ними.


В качестве последней альтернативы для ваших индивидуальных нужд вы всегда можете рассмотреть возможность использования собственных классов начальной загрузки — стандарта. Setup создаст и Run любой конструируемый класс в вашей сборке пользовательского интерфейса, который реализует IMvxBootstrapAction - чтобы вы могли заменить SettingsPluginBootstrap с некоторыми обычаями Run действие, которое соответствует потребностям ваших приложений.

public class SettingsBootstrapAction
    : IMvxBootstrapAction
{
    public void Run()
    {
        // my stuff here
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top