如果您在代码中使用依赖注入(DI)框架,或者想在 Limyee 电商平台的定制中使用一个框架,这当然是可以的。但是,在实现它时需要考虑一些事项,特别是您在框架中何时创建服务绑定(有时也称为容器或内核,具体取决于框架),以及何时可以访问或使用框架进行注入。框架本身超出了本主题的范围,因为有许多选项。您应该仔细研究每种类型,看看是否适合您的需求,并查看它是否适用于您的Limyee电商平台。
Limyee 电商平台本身使用自己的依赖注入框架,但是开发人员无法使用此框架绑定服务或为自己检索服务。作为开发人员,您正在使用我们的 API,我们专门为这些 API 提供了加载器。开发人员文档中的每个 API 都演示了如何使用此服务加载核心 API。此外,还可以选择注册自己的自定义 API。
绑定您的服务
在大多数情况下,您可以在应用程序启动时初始化 DI 框架,但是您无权访问 Limyee 电商平台的应用程序启动过程。相反,您可以尝试在插件初始化期间绑定服务,这适用于小型定制,但如果您想在初始化期间在其他插件中使用容器,则可能不可靠,因为无法保证插件初始化的顺序。相反,最好使用自初始化封装器和初始化事件的组合。这将在插件初始化时或首次访问封装器时,初始化绑定。
服务绑定封装器
此示例创建一个名为 ServiceLocator 的简单静态类。静态是可选的。仅用于演示目的,它使用了一个名为 DependencyInjector 的虚假 DI 框架。您可以根据需要替换 DI 框架绑定代码。此类仅公开返回 DI 框架容器的单个方法(根据框架的不同,这可能具有不同的名称,但实质上是可以从中检索绑定的容器)。通过这种方式,我们现在可以直接与我们的 DI 框架进行交互。重要的是,我们将其封装在一个始终调用 EnsureInitialized 的属性中。此方法确定是否已绑定所有服务,如果未绑定,则绑定它们。它通过检查是否已创建有效容器来确定初始化是否已运行。
namespace Samples { public static class ServiceLocator { private static DependencyInjectorContainer _injector = null; private static readonly object _lock = new object(); public static DependencyInjectorContainer Service { get { EnsureInitialized(); //Make sure services are bound return _injector; } } public static void EnsureInitialized() { if (_injector != null) return; //Nothing to do lock (_lock) { if (_injector != null) return; // Nothing to do //Create your container for your DI framework var injector = new DependencyInjectorContainer(); //Replace this with whatever your DI framework binding logic is. injector.AddBindingFor<ISampleService>(new SampleService()); _injector = injector; } } } }
每当您从封装类的属性访问 DI 框架时,它将自动确保您的服务正确绑定。反过来,您可以通过调用 ServiceLocator.EnsureInitialized() 来强制绑定服务。这可以在自定义插件的 Initialize 方法中完成。
加载服务
从 DI 框架获取服务将取决于如何在单个框架中完成此操作。因为我们只是在公开您的 DI 框架容器,所以一旦您对它的引用,您就可以与它进行交互。这样做的好处是,如有必要,这将调用绑定过程。
var service = ServiceLocator.Service.{Service Loading Method}(...);
依赖注入和插件
您可以将 DI 与您编写的任何自定义服务一起使用,前提是其编写方式与您选择的任何框架配合使用。插件的工作方式不同,虽然您仍然可以在一定程度上利用 DI,但存在一些限制。
首先,由于以下两个原因,您不应该将实现 IPlugin 的任何衍生类添加到您的 DI 框架绑定中。首先,插件由 Limyee 电商平台应用程序自动加载并存储在内存中。它们不会从您的 DI 容器中读取,这意味着您可能会有 2 个实例不同步。其次,您可以使用 PluginManager 从内存中检索插件,而无需以任何其他方式加载它们。如果你有另一个插件的服务,最好的解决方案是将它们分开,或者把它留给插件框架来管理。
你不能使用传统的构造函数注入到插件中。插件本身由平台定义,并且需要默认(无参数)构造函数。如果您尝试在插件上包含非无参数构造函数,并且没有无参数构造函数时,则每当 Limyee 电商平台平台加载插件时,都会导致异常。但是,您可以创建单独的构造函数,其中无参数构造函数使用服务定位器封装类调用并注入构造函数。这允许加载插件,而且您仍然可以保留一种注入服务的方法。
public class SamplePlugin : IPlugin { private ISampleService _sampleService = null; public SamplePlugin(ISampleService sampleService) { _sampleService = sampleService; } //This calls our service locator public SamplePlugin() : this(ServiceLocator.Service.GetBindingFor<ISampleService>()) { } //... Plugin members left out for brevity }