C++ 九阴真经之控制反转 Ioc

    控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)

    实现代码:

#include <sstream>
#include <string>
#include <unordered_map>
#include <memory>
#include <functional>
#include "anyval.h"
#include "noncopyable.h"
#include "singleton.h"



class IocContainer : public noncopyable
{
public:
	IocContainer() {}
	~IocContainer() {}

	template<class T, typename Depend, typename... Args>
	typename std::enable_if<!std::is_base_of<T, Depend>::value>::type RegisterType(const std::string& strKey)
	{
		std::function<T* (Args...)> function = [](Args... args) {
			return new Depend(args...);
		};

		RegisterType(strKey, function);
	}

	template<class T, typename Depend, typename... Args>
	typename std::enable_if<std::is_base_of<T, Depend>::value>::type RegisterType(const std::string& strKey)
	{
		std::function<T* (Args...)> function = [](Args... args) {
			return new Depend(args...);
		};

		RegisterType(strKey, function);
	}

	template<class T, typename... Args>
	T* Resolve(const std::string& strKey, Args... args)
	{
		auto iter = m_creatorMap.find(strKey);
		if (m_creatorMap.end() == iter)
		{
			return NULL;
		}

		AnyVar resolver = iter->second;
		std::function<T* (Args...)> function = any_cast<std::function<T* (Args...)>>(resolver);
		return function(args...);
	}

	template<class T, typename... Args>
	std::shared_ptr<T> ResolveShared(const std::string& strKey, Args... args)
	{
		T* tmp = Resolve<T, Args...>(strKey, args...);
		return std::shared_ptr<T>(tmp);
	}

private:
	void RegisterType(const std::string& strKey, AnyVar constructor)
	{
		if (m_creatorMap.end() != m_creatorMap.find(strKey))
		{
			throw std::invalid_argument(strKey + " : this key has already exist!");
		} 
		else
		{
			m_creatorMap.emplace(strKey, constructor);
		}
	}

private:
	std::unordered_map<std::string, AnyVar> m_creatorMap;
};



typedef Singleton<IocContainer> IocContainerAgent;

测试代码:
 

class TestBase
{
public:
    virtual  void show() = 0;
};

class TestIoc : public TestBase
{
public:
    TestIoc(int a, const std::string& msg)
    {

    }
    void show()
    {
        std::cout << "this is TestIoc" << std::endl;
    }
};

int main()
{
    IocContainerAgent::get_instance().RegisterType<TestBase, TestIoc, int, std::string>("testIoc");

    TestBase* pTest = IocContainerAgent::get_instance().Resolve<TestBase>("testIoc", 10, std::string("msg"));
    pTest->show();
    return 1;
}

 

栏目