依赖注入(DI)简介
依赖注入是一种技术,允许对象在创建时接收其依赖项,而不是在内部创建它们。DIPP(C++的依赖注入库)旨在尽可能接近.NET的Microsoft Dependency Injection。
DIPP的特点
- 非侵入式:可以与现有类一起使用。
- 无自动注册:必须显式注册服务。
- 单次注册:所有服务使用
dipp::service_collection一次性注册,并指定描述符(作用域生命周期如瞬态、范围或单例、对象的内存支持和对象的依赖项),之后可通过dipp::service_provider使用。 - 可扩展性与灵活性:可以定义自己的服务存储,
dipp::service_provider和dipp::service_collection是模板存储,默认使用std::map的dipp::move_only_any。
错误处理模式
DIPP支持两种模式:使用Boost.Leaf的错误返回值和在尝试获取或添加服务时抛出异常(可参考error_handling.cpp中的示例)。
键控服务支持
类似于.NET,DIPP支持键控服务,可以使用不同的键实例化多个相同类型的服务(可参考keys.cpp中的示例)。
代码示例
struct Engine {
Window& window1;
Window& window2;
Engine(Window& window1, Window& window2) : window1(window1), window2(window2) { }
};
// 声明我们的服务
using WindowService1 = dipp::injected<Window, ...>;
using WindowService2 = dipp::injected<Window, ..., dipp::key("UNIQUE")>;
using EngineService = dipp::injected<Engine, ..., dipp::dependency<WindowService1, WindowService2>>;
// 创建一个集合以持有我们的服务
dipp::service_collection collection;
// 将服务添加到集合中
collection.add<WindowService>();
collection.add<EngineService>();
// 创建一个服务提供者
dipp::service_provider services(std::move(collection));
// 获取服务
Engine& engine = services.get<EngineService>();
// 两个窗口服务不应该相同
assert(&engine.window1 != &engine.window2);
资源链接
博主点评: DIPP库通过灵活的依赖注入机制,给C++开发者带来了类似于.NET的体验,尤其适合于大型项目的模块化开发,值得深入研究与应用!