简体   繁体   中英

MvvmCross vnext: merge plugins with monodroid

I'm trying to merge plugins library projects into a single one (for example, Location + PhoneCallTask). It works perfectly with wp7, but I get an unhandled exception with monodroid:

Could not load file or assembly 'Cirrious.MvvmCross.Plugins.Location.Droid.dll'

Of course, the location plugin is referenced in 'Cirrious.MvvmCross.Plugins.Droid.dll', the merged library.

Is there a way to point to the merged library path?

Having considered your question more fully...

I'm still not entirely sure what a merge plugin is, but I think the problem you are seeing must be down to the way that MvvmCross-MonoDroid uses file conventions to load plugins while all the other platforms force the user to provide explicit factory methods for each plugin.

The reason for this difference is because the file conventions are (IMO) the nicest way of doing this... but all the other platforms put security and/or compilation issues in the way which meant that alternative mechanisms had to be used...

The easiest thing for you to do is probably to switch the setup of your MonoDroid app to use the loader conventions too.

To do this:

  • in Setup.cs override CreatePluginManager() to:

     protected override IMvxPluginManager CreatePluginManager() { var toReturn = new MvxLoaderBasedPluginManager(); var registry = new MvxLoaderPluginRegistry(".Droid", toReturn.Loaders); AddPluginsLoaders(registry); return toReturn; } 

and then provide a AddPluginsLoaders() implementation like:

    protected virtual void AddPluginsLoaders(Cirrious.MvvmCross.Platform.MvxLoaderPluginRegistry loaders)
    {
        loaders.AddConventionalPlugin<Cirrious.MvvmCross.Plugins.Visibility.Droid.Plugin>();
        loaders.AddConventionalPlugin<Cirrious.MvvmCross.Plugins.Location.Droid.Plugin>();
        loaders.AddConventionalPlugin<Cirrious.MvvmCross.Plugins.Phone.Droid.Plugin>();
        loaders.AddConventionalPlugin<AlphaPage.MvvmCross.Plugins.Mega.Droid.Plugin>();
        // etc
    }

Short answer:

I'm guessing you need to:

  • check that your namespaces and assembly names are all of the same convention
  • check that you have referenced both the core plugin assembly and the correct plugin implementation within the UI.Droid project

Longer answer (based on some notes I already had - will be published soon):

If you were to build an entirely new plugin, then you would:

1. Create a central shared plugin

This would be Portable Class library - say AlphaPage.MvvmCross.Plugins.Mega

Within that central shared PCL, you would put whatever portable code was available - often this might only be a few service Interface definitions - eg

public interface IAlphaService { ... }

and

public interface IPageService { ... }

You'd then add the PluginManager for that plugin which would just add the boiler-plate of:

public class PluginLoader
    : IMvxPluginLoader
    , IMvxServiceConsumer<IMvxPluginManager>
{
    public static readonly PluginLoader Instance = new PluginLoader();

    #region Implementation of IMvxPluginLoader

    public void EnsureLoaded()
    {
        var manager = this.GetService<IMvxPluginManager>();
        manager.EnsureLoaded<PluginLoader>();
    }

    #endregion
}

2. Create the specific plugin implementations

For each platform, you would then implement the plugin - eg you might implement AlphaPage.MvvmCross.Plugins.Mega.WindowsPhone and AlphaPage.MvvmCross.Plugins.Mega.Droid

Within each of these you will implement the native classes which provide the services:

public class MyAlphaService : IAlphaService { ... } 

and

public class MyPageService : IPageService { ... }

Finally each plugin would then provide the boilerplate plugin implementation:

public class Plugin
    : IMvxPlugin
    , IMvxServiceProducer
{
    #region Implementation of IMvxPlugin

    public void Load()
    {
        // alpha registered as a singleton
        this.RegisterServiceInstance<IAlphaService>(new MyAlphaService());
        // page registered as a type
        this.RegisterServiceType<IPageService, MyPageService>();
    }

    #endregion
}

3. Instantiation of plugins

Each UI client will have to initialise the plugins.

This is done by the end UI client adding library references to:

  • the shared core plugin
  • the appropriate plugin implementation

3.1 WinRT, WindowsPhone and MonoTouch

Then, for WinRT, WindowsPhone and MonoTouch clients, you also need to provide a Loader accessor in setup.cs - like:

    protected override void AddPluginsLoaders(Cirrious.MvvmCross.Platform.MvxLoaderPluginRegistry loaders)
    {
        loaders.AddConventionalPlugin<AlphaPage.MvvmCross.Plugins.Mega.WindowsPhone.Plugin>();
        base.AddPluginsLoaders(loaders);
    }

Note that Convention is used here - so it's important that AlphaPage.MvvmCross.Plugins.Mega.WindowsPhone.Plugin implements the WindowsPhone plugin for AlphaPage.MvvmCross.Plugins.Mega.PluginLoader

3.2 MonoDroid

For MonoDroid clients, you don't need to add this setup step - because MonoDroid has less Assembly.Load restrictions than the other platforms - and ao can load the plugins from file. But for this to work, it's important that the assembly names match - if the PluginLoader is AlphaPage.MvvmCross.Plugins.Mega.PluginLoader then the conventions will try to load the plugin from AlphaPage.MvvmCross.Plugins.Mega.Droid.dll

4. Use of plugin services

After this setup, then applications should finally be able to access the plugins by:

  • adding a reference the Shared core portable library
  • at some time calling AlphaPage.MvvmCross.Plugins.Mega.PluginLoader.Instance.EnsureLoaded()
  • then accessing the individual services using this.GetService<IAlphaService>() or this.GetService<IPageService>()

5. Pure portable plugins

Some plugins can be 'pure portable'

In this case they don't need any specialization for each platform, and no step 3 is required.

For an example of this, see the Json implementation - https://github.com/slodge/MvvmCross/tree/vnext/Cirrious/Plugins/Json

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM