PCL 延伸路线
如何通过扩展 PCL 来做到这一点......我不完全确定!其中一位 PCL 人员可能会提供帮助。
插件路由
我解决这个问题的方法是在接口中定义我想要的功能并将代码包装在插件中。
例如,Cheesebaron.Plugins.Gzip.dll
您可以创建如下界面:
public interface IGZipStreamFactory
{
Stream Decompress(Stream binaryStream);
}
然后这个接口会被插入到一个只包含这个接口和 pluginmanager 类的 PCL 库中。
然后,您的 PCL 核心项目可以引用此 PCL 插件库,并且您的 ViewModel 可以使用如下代码:
Cheesebaron.Plugins.GZip.PluginLoader.Instance.EnsureLoaded();
其次是
var service = this.GetService<IGZipStreamFactory>();
var unzipped = service.Decompress(inputStream);
对于每个实际的平台实现,您需要准备一个特定于平台的库,实现 GZip 工厂接口,并提供一个简单的Plugin
类实现。
例如,对于 Droid,您可以创建Cheesebaron.Plugins.Gzip.Droid.dll
:
public class MyDroidGZipStreamFactory : IGZipStreamFactory
{
// the implementation
}
然后你会添加:
public class Plugin
: IMvxPlugin
, IMvxServiceProducer
{
public void Load()
{
this.RegisterServiceInstance<IGZipStreamFactory>(new MyDroidGZipStreamFactory));
}
}
最后... 将它们组合在一起,对于 MonoDroid,您可以在您的 UI 项目中同时引用 PCL 和特定于平台的实现——它应该都可以工作!
请注意,这里在幕后发生了一些基于约定的魔术 - 框架Cheesebaron.Plugins.Gzip.Droid.dll
根据 PCL 插件命名空间加载程序集Cheesebaron.Plugins.Gzip
(对于 WP7 和其他平台,还有一个额外的步骤 - 有一种设置方法来覆盖注册插件的方法)
请注意,您可以在单个插件中注册任意数量的服务,也可以执行额外的常见初始化/设置代码。这有助于减少一些项目维护开销:如果愿意,您可以将 CheeseBaron IoC 对象放在一个CheeseBaron.Plugins.Utils
项目中,然后在所有应用程序中共享这个插件。
该DownloadCache
插件提供了一个小示例 - 它注册了所有IMvxHttpFileDownloader
,IMvxImageCache
和IMvxLocalFileImageLoader
.
这样做的缺点是:最终链接的 exe 大小 - 您可能会向每个应用程序添加不需要的代码。
显然,这种插件方法有一点学习曲线......它确实增加了一些项目维护 - 但好消息是这些插件可以在项目之间反复使用 - 并且可以在组织之间共享(在至少,这是我的希望!)
更多关于创建插件的信息:
有关插件示例(并非所有平台都可用),请参阅https://github.com/slodge/MvvmCross/tree/vnext/Cirrious/Plugins
其他路线
如果您不想使用插件 - 例如,如果您很匆忙,或者您正在为不想重用的模块编写代码,那么还有其他选择:
- 您可以在共享核心 PCL 库中定义类似 IGZipStreamFactory 的接口。然后,您可以在每个 UI 项目中提供此接口的特定于平台的实现,然后可以在 ViewModel/Model/Service 层中使用普通的 IoC/DI,以便在运行时找到正确的实现。
或者...
- 您可以只转储共享的 PCL 核心库并创建单独的特定于平台的 DLL,然后手动链接到特定于平台的文件中(我尽量不要这样做,但其他人喜欢这样做)