如何使用Kangaru C++自动装配功能简化依赖注入代码
基于Kangaru实现自动装配的依赖注入方案
当你尝试直接使用kgr::autowire实现BService时失败,核心原因是Kangaru自动装配无法默认推断抽象类型IA对应的服务实现。框架需要明确知道抽象接口与服务类的映射关系,以下是两种可行的解决方案:
方案一:注册抽象类型与服务的映射
通过特化kgr::service_map,告诉框架当需要IA类型实例时,使用IAService提供的实现:
#include <kangaru/kangaru.hpp> #include <iostream> struct IA { virtual void run() const = 0; }; struct A : IA { void run() const override { std::cout << "A" << std::endl; } }; struct IB { virtual void runB() const = 0; }; struct B : IB { IA& _a; B(IA& a) : _a(a) {} void runB() const override { std::cout << "B" << std::endl; } }; struct IAService : kgr::abstract_service<IA> {}; struct IBService : kgr::abstract_service<IB> {}; struct AService : kgr::single_service<A>, kgr::overrides<IAService> {}; // 关键:映射抽象类型IA到服务IAService namespace kgr { template<> struct service_map<IA> { using type = IAService; }; } // 使用autowire自动装配依赖 struct BService : kgr::single_service<B, kgr::autowire>, kgr::overrides<IBService> {}; int main() { kgr::container container; container.service<AService>().run(); container.service<IAService>().run(); container.service<BService>().runB(); container.service<IBService>().runB(); return 0; }
方案二:在构造函数中显式指定依赖服务
修改B的构造函数,使用kgr::inject<T>包装依赖的服务类型,让自动装配直接定位到IAService:
#include <kangaru/kangaru.hpp> #include <iostream> struct IA { virtual void run() const = 0; }; struct A : IA { void run() const override { std::cout << "A" << std::endl; } }; struct IB { virtual void runB() const = 0; }; struct B : IB { IA& _a; // 使用kgr::inject指定依赖的服务 B(kgr::inject<IAService> a) : _a(a.get()) {} void runB() const override { std::cout << "B" << std::endl; } }; struct IAService : kgr::abstract_service<IA> {}; struct IBService : kgr::abstract_service<IB> {}; struct AService : kgr::single_service<A>, kgr::overrides<IAService> {}; // 直接使用autowire即可 struct BService : kgr::single_service<B, kgr::autowire>, kgr::overrides<IBService> {}; int main() { kgr::container container; container.service<AService>().run(); container.service<IAService>().run(); container.service<BService>().runB(); container.service<IBService>().runB(); return 0; }
注意事项
- 原代码中的
void main()不符合C++标准,需改为int main()并返回0,避免编译器兼容性问题。 - 两种方案都能实现自动装配,选择哪种取决于你的代码风格:方案一更适合全局统一映射抽象类型,方案二则更直观地在构造函数中声明依赖服务。
内容的提问来源于stack exchange,提问作者Y.H.Cohen
相关产品推荐
相关产品推荐

