下面是这个是可以实现无参的IoC容器
#include <string> #include <map> #include <memory> #include <functional> #include <iostream> #include <vector> #include <any> #include <unordered_map> class IocContainer { private: std::unordered_map<std::string, std::any> m_creatorMap; private: void RegisterType(const std::string &strKey, std::any constructor) { if (m_creatorMap.find(strKey) != m_creatorMap.end()) { throw std::invalid_argument("this key has already exist"); } m_creatorMap.emplace(strKey, constructor); } public: IocContainer(void) {} ~IocContainer(void) {} //注册需要创建对象的构造函数,需要传入一个唯一的标识,以便在后面创建对象时方便查找 template <class T, class Depend> void RegisterType(std::string strKey) { std::function<T*()> function = [] { return new T(new Depend()); }; RegisterType(strKey, function); } //根据唯一的标w识去查找对应的构造器,并创建指针对象 template<class T> T* Resolve(const std::string& strKey) { if (m_creatorMap.find(strKey) == m_creatorMap.end()) { return nullptr; } std::any resolver = m_creatorMap[strKey]; /*std::function<T*()> function = m_creatorMap[strKey];*/ std::function<T*()> function = std::any_cast<std::function<T*()>>(resolver); return function(); } //创建智能指针对象 template<class T> std::shared_ptr<T> ResolveShared(const std::string& strKey) { T* ptr = Resolve<T>(strKey); return std::shared_ptr<T>(ptr); } }; struct Base { virtual void Func()=0; virtual ~Base(){} }; struct DerivedB :Base { void Func() override { std::cout << "call func in DerivedB" << std::endl; } }; struct DerivedC :Base { void Func() override { std::cout << "call func in DerivedC" << std::endl; } }; struct DerivedD :Base { void Func() override { std::cout << "call func in DerivedD" << std::endl; } }; struct A { A(Base *ptr):m_ptr(ptr){} void Func() { m_ptr->Func(); } ~A() { if (m_ptr!=nullptr) { delete m_ptr; m_ptr = nullptr; } } private: Base *m_ptr; }; void TestIOC() { IocContainer ioc; ioc.RegisterType<A, DerivedB>("B"); ioc.RegisterType<A, DerivedC>("C"); ioc.RegisterType<A, DerivedD>("D"); auto paB = ioc.ResolveShared<A>("B"); paB->Func(); auto paC = ioc.ResolveShared<A>("C"); paC->Func(); } int main() { TestIOC(); return 0; }
如果想要实现有参的,那么需要使用C++11可变模板参数:
#include <string> #include <map> #include <memory> #include <functional> #include <iostream> #include <vector> #include <any> #include <unordered_map> //#include "NonCopyable.hpp" class IocContainer { std::unordered_map<std::string, std::any> m_creatorMap; private: void RegisterType(const std::string &strKey, std::any constructor) { if (m_creatorMap.find(strKey) != m_creatorMap.end()) { throw std::invalid_argument("this key has already exist"); } m_creatorMap.emplace(strKey, constructor); } public: IocContainer() {} ~IocContainer() {} template<class T, class Depend, class ...Args> void RegisterType(const std::string& strKey) { std::function<T*(Args...)> function = [](Args... args) { return new T(new Depend(args...)); }; RegisterType(strKey, function); } template<class T, class ...Args> T* Resolve(const std::string& strKey, Args... args) { if (m_creatorMap.find(strKey) == m_creatorMap.end()) { return nullptr; } std::any resolver = m_creatorMap[strKey]; std::function<T*(Args...)> function = std::any_cast<std::function<T*(Args...)>>(resolver); return function(args...); } //创建智能指针对象 template<class T, class ...Args> std::shared_ptr<T> ResolveShared(const std::string& strKey, Args... args) { T* ptr = Resolve<T>(strKey, args...); return std::shared_ptr<T>(ptr); } }; struct Base { virtual void Func() {} virtual ~Base() {} }; struct DerivedB :public Base { DerivedB(int a, double b) :m_a(a), m_b(b) { } void Func() override { std::cout << m_a + m_b << std::endl; } private: int m_a; double m_b; }; struct DerivedC :Base { void Func() override { std::cout << "call func in DerivedC" << std::endl; } }; struct A { A(Base *ptr) :m_ptr(ptr) {} void Func() { m_ptr->Func(); } ~A() { if (m_ptr != nullptr) { delete m_ptr; m_ptr = nullptr; } } private: Base *m_ptr; }; void TestIoC() { IocContainer ioc; ioc.RegisterType<A, DerivedB, int, double>("B"); auto b = ioc.ResolveShared<A>("B", 1, 2.0); ioc.RegisterType<A, DerivedC>("C"); auto c = ioc.ResolveShared<A>("C"); b->Func(); c->Func(); } int main() { TestIoC(); return 0; }
IoC(依赖注入)有好几种,C#和java中支持构造函数,属性和普通函数调用注入。但是由于C++不支持反射和标签,不能实现后2种,目前只能做到构造函数的依赖注入。
代码来自思路来着<<深入应用C++11:代码优化与工程级应用>> 祁宇,第11章。
书中有部分错误,我已修改