问题
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?
回答1:
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
}
回答2:
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 - e.g.
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 - e.g. 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>()orthis.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
来源:https://stackoverflow.com/questions/12931618/mvvmcross-vnext-merge-plugins-with-monodroid