Pregunta

Tengo un problema al usar mis propios complementos MvvmCross en un proyecto de Android, porque el PluginLoader parece esperar un .Droid.dll del espacio de nombres exacto en el que se encuentra.

Digamos que tengo tres proyectos con esta estructura de carpetas y espacios de nombres:

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

El proyecto de iOS funciona tal como se esperaba y encuentra el complemento sin problemas.

El proyecto Droid, por otro lado, falla con una excepción: Could not load file or assembly 'MyApp.Plugins.Settings.Droid.dll' or one of its dependencies.

Si cambio el espacio de nombres del PluginLoader de MyApp.Core.Plugins.Settings simplemente MyApp, el complemento funciona;Supongo que busca el MyApp.dll y lo encuentra.Sin embargo, si tengo varios complementos en mi aplicación, cada uno debería tener su propio espacio de nombres, no todos pueden estar en el MyApp espacio de nombres.

Actualmente, la única solución que he encontrado es crear un proyecto separado para cada complemento que creo, aunque esto parece un poco innecesario.

¿Por qué el PluginLoader Insistir en buscar el <PluginLoader namespace>.Droid.dll archivo en Android, cuando el PluginLoader ¿En iOS encuentra el complemento sin ningún problema?

¿Fue útil?

Solución

Los complementos de MvvmCross están diseñados para funcionar como una capa basada en ensamblaje encima de IoC.

Al utilizar un patrón compartido para espacios de nombres y ensamblados, junto con un par de clases auxiliares (Plugin y PluginLoader), los complementos proporcionan una forma de compartir y reutilizar componentes de código nativo portátiles.

La razón por la cual iOS (y Mac) usan un esquema de carga de complementos ligeramente diferente es porque el compilador AoT de MonoTouch no permitirá cargas dinámicas. Assembly.Load cargando.

Debido a esto, iOS tiene que usar un tipo diferente de PluginManager y un tipo diferente de Bootstrap clase a las otras plataformas.Hay un poco más de información sobre esto en "Cómo se cargan los complementos" en https://github.com/MvvmCross/MvvmCross/wiki/MvvmCross-plugins#how-plugins-are-loaded


Si quisieras agregar el Loader escriba el registro de complementos para Android y iOS, entonces creo que podría hacer esto de forma personalizada PluginManager clase y luego podría crear esto durante la instalación usando una anulación de protected override IMvxPluginManager CreatePluginManager().

Algo como:

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

inicializado en su configuración usando:

    protected override IMvxPluginManager CreatePluginManager()
    {
        return new MyPluginManager(".Droid", ".dll");
    }

entonces deberá asegurarse de que su loader Los complementos basados ​​​​utilizan clases de arranque basadas en MvxLoaderPluginBootstrapAction y no MvxPluginBootstrapAction


Como otra alternativa, si no está interesado en reutilizar sus complementos individualmente (si prefiere no enviar muchos conjuntos de complementos individuales), entonces podría colocar todas sus interfaces e implementaciones en un solo conjunto, y luego podrían compartir un solo conjunto. Bootstrap, Plugin y PluginLoader entre ellos.


Como última alternativa, para sus necesidades personalizadas, siempre puede considerar el uso de sus propias clases de arranque personalizadas: el estándar Setup creará y Run cualquier clase construible en su ensamblaje de UI que implemente IMvxBootstrapAction - para que puedas reemplazar SettingsPluginBootstrap con alguna costumbre Run acción que se adapta a las necesidades de sus aplicaciones.

public class SettingsBootstrapAction
    : IMvxBootstrapAction
{
    public void Run()
    {
        // my stuff here
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top