Frage

Ich habe ein Problem mit der Verwendung meiner eigenen MvvmCross-Plugins in einem Android-Projekt, weil die PluginLoader scheint eine zu erwarten .Droid.dll des genauen Namensraums, in dem es sich befindet.

Angenommen, ich habe drei Projekte mit dieser Ordner- und Namespace-Struktur:

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

Das iOS-Projekt funktioniert wie erwartet und findet das Plugin problemlos.

Das Droidenprojekt hingegen schlägt mit einer Ausnahme fehl: Could not load file or assembly 'MyApp.Plugins.Settings.Droid.dll' or one of its dependencies.

Wenn ich den Namespace des ändere PluginLoader von MyApp.Core.Plugins.Settings zu einfach MyApp, das Plugin funktioniert;Ich denke, es sucht nach dem MyApp.dll und findet es.Wenn ich jedoch mehrere Plugins in meiner App habe, sollten sie jeweils ihren eigenen Namespace haben, sie können nicht alle in der MyApp namensraum.

Derzeit besteht die einzige Problemumgehung, die ich gefunden habe, darin, für jedes von mir erstellte Plugin ein separates Projekt zu erstellen, obwohl dies sich etwas unnötig anfühlt.

Warum funktioniert die PluginLoader bestehen Sie darauf, nach dem zu suchen <PluginLoader namespace>.Droid.dll datei auf Android, wenn die PluginLoader auf iOS findet das Plugin ohne Probleme?

War es hilfreich?

Lösung

MvvmCross-Plugins sind so konzipiert, dass sie als assemblybasierte Ebene über IoC funktionieren.

Durch die Verwendung eines gemeinsam genutzten Musters für Namespaces und Assemblys sowie einiger Hilfsklassen (Plugin und PluginLoader) bieten Plugins die Möglichkeit, portable native Codekomponenten gemeinsam zu nutzen und wiederzuverwenden.

Der Grund, warum iOS (und Mac) ein etwas anderes Plugin-Ladeschema verwenden, liegt darin, dass der AOT-Compiler von MonoTouch keine Dynamik zulässt Assembly.Load laden.

Aus diesem Grund muss iOS einen anderen Typ von verwenden PluginManager und eine andere Art von Bootstrap klasse zu den anderen Plattformen.Es gibt ein bisschen mehr Informationen dazu in "Wie Plugins geladen werden" in https://github.com/MvvmCross/MvvmCross/wiki/MvvmCross-plugins#how-plugins-are-loaded


Wenn Sie das hinzufügen möchten Loader geben Sie die Plugin-Registrierung sowohl für Android als auch für iOS ein, dann denke ich, dass Sie dies in einem benutzerdefinierten tun könnten PluginManager klasse und könnte diese dann während des Setups mit einer Überschreibung von erstellen protected override IMvxPluginManager CreatePluginManager().

So etwas wie:

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

initialisiert in Ihrem Setup mit:

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

sie müssten dann sicherstellen, dass Ihre loader basierte Plugins verwenden Bootstrap-Klassen basierend auf MvxLoaderPluginBootstrapAction und nicht MvxPluginBootstrapAction


Wenn Sie nicht daran interessiert sind, Ihre Plugins einzeln wiederzuverwenden - wenn Sie lieber nicht viele einzelne Plugin-Assemblys versenden möchten -, können Sie alternativ alle Ihre Schnittstellen und Implementierungen in einer einzigen Assembly zusammenfassen - und sie könnten dann eine einzige teilen Bootstrap, Plugin und PluginLoader dazwischen.


Als letzte Alternative können Sie für Ihre benutzerdefinierten Anforderungen immer die Verwendung Ihrer eigenen benutzerdefinierten Bootstrap-Klassen in Betracht ziehen - der Standard Setup wird erstellen und Run jede konstruierbare Klasse in Ihrer UI-Assembly, die implementiert IMvxBootstrapAction - so könnten Sie ersetzen SettingsPluginBootstrap mit etwas Brauch Run aktion, die Ihren Apps-Anforderungen entspricht.

public class SettingsBootstrapAction
    : IMvxBootstrapAction
{
    public void Run()
    {
        // my stuff here
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top