Come utilizzare i plugin Mvvmcross in Android senza compilare DLL?
Domanda
Ho un problema usando i miei plugin Mvvvmcross in un progetto Android, perché il PluginLoader
sembra aspettarsi un .Droid.dll
dello spazio dei nomi esatti è in.
Dì che ho tre progetti con questa cartella e struttura dei nomi Struttura:
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
.
Il progetto iOS funziona altrettanto previsto e trova il plugin senza problemi.
Il progetto Droid d'altra parte, fallisce con un'eccezione: Could not load file or assembly 'MyApp.Plugins.Settings.Droid.dll' or one of its dependencies.
Se modifico lo spazio dei nomi del PluginLoader
da MyApp.Core.Plugins.Settings
per semplicemente MyApp
, il plugin funziona; Immagino che cerca il MyApp.dll
e lo trova. Tuttavia, se ho più plugin nella mia app, dovrebbero avere ciascuno il proprio spazio dei nomi, non possono essere tutti nello spazio dei nomi MyApp
.
Attualmente l'unica soluzione alternativa che ho trovato è creare un progetto separato per ciascun plugin che creo, anche se questo è un po 'inutile.
Perché il PluginLoader
insiste sulla ricerca del file <PluginLoader namespace>.Droid.dll
su Android, quando il PluginLoader
su IOS trova il plugin senza alcun problema?
Soluzione
I plugin MVVMCross sono progettati per funzionare come livello basato su assembly in cima a IOC.
Utilizzando un modello condiviso per i nomi spazi e gli assembly, insieme a un paio di classi di helper (plugin e pluginloader), i plugin forniscono un modo per condividere e riutilizzare i componenti del codice nativo portatili.
Il motivo per cui iOS (e Mac) Utilizzare uno schema di caricamento del plugin leggermente diverso è dovuto al fatto che il compilatore AOT monotauch non consentirà il caricamento dinamico Assembly.Load
.
A causa di questo iOS deve utilizzare un tipo diverso di PluginManager
e un tipo diverso di classe Bootstrap
alle altre piattaforme. Ci sono un po 'più informazioni su questo in "Come i plugin sono caricati" in https://github.com/mvvmcross/mvvmcross/wiki/mvvmcross-plugins#How-Plugins-are- caricato
.
Se si desidera aggiungere il registro dei plugin di tipo Loader
a Android e IOS, quindi ritengo che tu possa farlo in una classe PluginManager
personalizzata e potrebbe quindi crearlo durante la configurazione utilizzando un'override di protected override IMvxPluginManager CreatePluginManager()
.
Qualcosa come:
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);
}
}
.
Inizializzato nella configurazione utilizzando:
protected override IMvxPluginManager CreatePluginManager()
{
return new MyPluginManager(".Droid", ".dll");
}
.
Dovresti quindi garantire che i tuoi plugin basati su loader
utilizzino le classi di bootstrap basate su MvxLoaderPluginBootstrapAction
e non MvxPluginBootstrapAction
.
Come un'altra alternativa, se non sei interessato a riutilizzare singolarmente i tuoi plugin - se preferisci non spedire un sacco di singoli gruppi di plugin - allora puoi mettere tutte le tue interfacce e implementazioni in un unico assembly - e potrebbero quindi condividere A Singolo Bootstrap
, Plugin
e PluginLoader
tra di loro.
.
Come alternativa finale, per le tue esigenze personalizzate, è sempre possibile considerare di utilizzare le tue classi di bootstrap personalizzate - il Setup
standard creerà e Run
qualsiasi classe costruttiva nel tuo assemblaggio dell'interfaccia utente che implementa IMvxBootstrapAction
- in modo da poter sostituire SettingsPluginBootstrap
con alcuni personalizzati Run
Action che si adatta alle tue esigenze di app.
public class SettingsBootstrapAction
: IMvxBootstrapAction
{
public void Run()
{
// my stuff here
}
}
.