C++ 公共组件-IOC库
IOC机制简介
IOC机制可以让对象之间的关系在外面组装,外界可以根据需求灵活地配置这种机制的对象创建策略,从而获得想要的目标对象,这种机制被称为控制反转(Inversion of Control,IoC)。
控制反转就是应用本身不负责依赖对象的创建和维护,而交给一个外部容器来负责。这样控制权就由应用转移到了外部IoC容器,即实现了所谓的控制反转。IoC用来降低对象之间直接依赖产生的耦合性。
IOC的简单实现
github项目地址
Any.hpp(C++17之前使用)
#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使用)
#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使用)
#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(测试用例)
#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;
}