C ++ public library components -IOC

C ++ public library components -IOC

Reference URL: https: //blog.csdn.net/alpha_love/article/details/75208889

IOC mechanisms Introduction

IOC mechanism can make the relationship between objects outside the assembly, the outside world can be flexibly configured according to the object of such a mechanism needs to create a strategy to obtain target audience wants, this mechanism is known as inversion of control (Inversion of Control, IoC).

Inversion of Control is the application itself is not responsible for creating and maintaining dependent objects, and to an external container to be responsible. Such control shifts to the outside by the application IoC container, i.e. to achieve a so-called inversion of control. IoC for reducing coupling between objects generated is directly dependent.
Specifically refer to this URL: https: //blog.csdn.net/alpha_love/article/details/75208889

Simple implementation of the IOC

github project address

Any.hpp (C ++ 17 before use)

#pragma once
#include <memory>
#include <typeindex>
#include <exception>
#include <iostream>

struct Any
{
	Any(void) : m_tpIndex(std::type_index(typeid(void))) {}
	Any(const Any& that) : m_ptr(that.Clone()), m_tpIndex(that.m_tpIndex) {}
	Any(Any && that) : m_ptr(std::move(that.m_ptr)), m_tpIndex(that.m_tpIndex) {}

	//创建智能指针时,对于一般的类型,通过std::decay来移除引用和cv符,从而获取原始类型
	template<typename U, class = typename std::enable_if<!std::is_same<typename std::decay<U>::type, Any>::value, U>::type> Any(U && value) : m_ptr(new Derived < typename std::decay<U>::type>(std::forward<U>(value))),
		m_tpIndex(std::type_index(typeid(typename std::decay<U>::type))){}

	bool IsNull() const { return !bool(m_ptr); }

	template<class U> bool Is() const
	{
		return m_tpIndex == std::type_index(typeid(U));
	}

	//将Any转换为实际的类型
	template<class U>
	U& AnyCast()
	{
		if (!Is<U>())
		{
			std::cout << "can not cast " << typeid(U).name() << " to " << m_tpIndex.name() << std::endl;
			throw std::logic_error{"bad cast"};
		}

		auto derived = dynamic_cast<Derived<U>*> (m_ptr.get());
		return derived->m_value;
	}

	Any& operator=(const Any& a)
	{
		if (m_ptr == a.m_ptr)
			return *this;

		m_ptr = a.Clone();
		m_tpIndex = a.m_tpIndex;
		return *this;
	}

    Any& operator=(Any&& a)
    {
        if (m_ptr == a.m_ptr)
            return *this;

        m_ptr = std::move(a.m_ptr);
        m_tpIndex = a.m_tpIndex;
        return *this;
    }

private:
	struct Base;
	typedef std::unique_ptr<Base> BasePtr;

	struct Base
	{
		virtual ~Base() {}
		virtual BasePtr Clone() const = 0;
	};

	template<typename T>
	struct Derived : Base
	{
		template<typename U>
		Derived(U && value) : m_value(std::forward<U>(value)) { }

		BasePtr Clone() const
		{
			return BasePtr(new Derived<T>(m_value));
		}

		T m_value;
	};

	BasePtr Clone() const
	{
		if (m_ptr != nullptr)
			return m_ptr->Clone();

		return nullptr;
	}

	BasePtr m_ptr;
	std::type_index m_tpIndex;
};

NonCopyable.hpp

#pragma once
class NonCopyable
{
public:
	NonCopyable(const NonCopyable&) = delete; // deleted
	NonCopyable& operator = (const NonCopyable&) = delete; // deleted
	NonCopyable() = default;   // available
};

Ioc_11.hpp (C ++ 11 use)

#pragma once
#include<string>
#include<unordered_map>
#include<memory>
#include<functional>
#include "Any.hpp"
#include "NonCopyable.hpp"

using namespace std;

class IocContainer : NonCopyable
{
public:
	IocContainer() = default;
	~IocContainer() = default;

	template<class T, typename Depend, typename... Args>
    typename std::enable_if<!std::is_base_of<T,Depend>::value>::type RegisterType(const string& strKey){
		std::function<T* (Args&&...)> function = [](Args&&... args){ return new T(new Depend(std::forward<Args>(args)...)); };//通过闭包擦除了参数类型
		RegisterType(strKey, std::move(function));
	}

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

    template <class T, typename... Args>
    void RegisterSimple(const string& strKey){
        std::function<T*(Args&&...)> function = [](Args&&... args){return new T(std::forward<Args>(args)...);};
        RegisterType(strKey,std::move(function));
    }

	template<class T, typename... Args>
	T* Resolve(const string& strKey, Args&&... args){
		if (m_creatorMap.find(strKey) == m_creatorMap.end())
			return nullptr;

		Any resolver = m_creatorMap[strKey];
		std::function<T* (Args&&...)> function = resolver.AnyCast<std::function<T* (Args&&...)>>();
		return function(std::forward<Args>(args)...);
	}

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

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

		//通过Any擦除了不同类型的构造器
		m_creatorMap.emplace(strKey, constructor);
	}

private:
	unordered_map<string, Any> m_creatorMap;
};

Ioc_17.hpp (C ++ 17 used)

#pragma once
#include<string>
#include<unordered_map>
#include<memory>
#include<functional>
#include <any>
#include "NonCopyable.hpp"

using namespace std;

class IocContainer : NonCopyable
{
public:
    IocContainer() = default;
    ~IocContainer() = default;

    template<class T, typename Depend, typename... Args>
    typename std::enable_if<!std::is_base_of<T,Depend>::value>::type RegisterType(const string& strKey){
        std::function<T* (Args&&...)> function = [](Args&&... args){ return new T(new Depend(std::forward<Args>(args)...)); };//通过闭包擦除了参数类型
        RegisterType(strKey, std::move(function));
    }

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

    template <class T, typename... Args>
    void RegisterSimple(const string& strKey){
        std::function<T*(Args&&...)> function = [](Args&&... args){return new T(std::forward<Args>(args)...);};
        RegisterType(strKey,std::move(function));
    }

    template<class T, typename... Args>
    T* Resolve(const 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(std::forward<Args>(args)...);
    }

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

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

        //通过Any擦除了不同类型的构造器
        m_creatorMap.emplace(strKey, constructor);
    }

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

main.cpp (test case)

#ifndef __CPP17
    #if __cplusplus > 201402L
    #       define __CPP17 (1)
    #else
    #       define __CPP17 (0)
    #endif
#endif

#ifndef __CPP14
    #if __cplusplus > 201103L
    #       define __CPP14 (1)
    #else
    #       define __CPP14 (0)
    #endif
#endif

#ifndef __CPP11
    #if __cplusplus > 199711L
    #       define __CPP11 (1)
    #else
    #       define __CPP11 (0)
    #endif
#endif

#if __CPP17
#include "Ioc_17.hpp"
#elif __CPP11
#include "Ioc_11.hpp"
#endif

#include <iostream>
using namespace std;

/*test code*/
//测试继承对象
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
	{
		cout<<"DerivedB::Fun()::"<<m_a+m_b<<endl;
	}
private:
	int m_a;
	double m_b;
};

struct DerivedC : public Base
{
    void Func()override
    {
        cout<<"DerivedC::Fun()"<<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;
};

//测试普通对象
struct Bus
{
    void Func() const { std::cout <<"Bus::Func()"<<std::endl; }
};
struct Car
{
    void Func() const { std::cout <<"Car::Func()"<<std::endl; }
};


void TestIoc(){
	IocContainer ioc;
	//注册继承对象
	ioc.RegisterType<A, DerivedC>("C");      //配置依赖关系
    ioc.RegisterType<A, DerivedB, int, double>("B");   //注册时要注意DerivedB的参数int和double

    //注册普通对象
    ioc.RegisterSimple<Bus>("Bus");
    ioc.RegisterSimple<Car>("Car");

	auto c = ioc.ResolveShared<A>("C");
    c->Func();
	auto b = ioc.ResolveShared<A>("B", 1, 2.0); //还要传入参数
	b->Func();

    auto bus = ioc.ResolveShared<Bus>("Bus");
    bus->Func();
    auto car = ioc.ResolveShared<Car>("Car");
    car->Func();

}

int main() {
    TestIoc();

    return 0;
}
Published 155 original articles · won praise 15 · views 160 000 +

Guess you like

Origin blog.csdn.net/wangdamingll/article/details/105067279