打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
(原创)C IOC框架

C++里面缺少一些有用的框架比如说AOP和IOC等,AOP框架的实现在前面的博文中已介绍了,现在介绍IOC框架。

IOC即控制反转,它的思想是由IOC容器来管理对象的生命周期、依赖关系等,从而使得应用程序的配置和依赖性规范与实际的应用程序代码分开。其中一个特点就是通过文本的配置文件进行应用程序组件间相互关系的配置,而不用重新修改并编译具体的代码。IOC不仅仅用来解除对象创建的耦合性,还可以使我们能通过配置去创建我们需要的对象,这种灵活性在我们应用开发过程中是非常有用的。C#和Java中有很多IOC框架,遗憾的是C++中却鲜有IOC框架,本IOC框架填补了这个遗憾。

IOC框架的实现原理:通过向IOC容器注册类型信息和一个唯一key,在创建时,根据类型信息和key从容器中创建一个实例。下面具体看实现代码:

#include <string>#include <map>#include <memory>#include <functional>using namespace std;#include <Any>#include<NonCopyable>class IocContainer : NonCopyable{public: IocContainer(void){} ~IocContainer(void){} template <class T> void RegisterType(string strKey) { typedef T* I; std::function<I()> function = Construct<I, T>::invoke; RegisterType(strKey, function); } template <class I, class T, typename... Ts> void RegisterType(string strKey) { std::function<I* (Ts...)> function = Construct<I*, T, Ts...>::invoke; RegisterType(strKey, function); } template <class I> I* Resolve(string strKey) { if (m_creatorMap.find(strKey) == m_creatorMap.end()) return nullptr; Any resolver = m_creatorMap[strKey]; std::function<I* ()> function = resolver.AnyCast<std::function<I* ()>>(); return function(); } template <class I> std::shared_ptr<I> ResolveShared(string strKey) { auto b = Resolve<I>(strKey); return std::shared_ptr<I>(b); } template <class I, typename... Ts> I* Resolve(string strKey, Ts... Args) { if (m_creatorMap.find(strKey) == m_creatorMap.end()) return nullptr; Any resolver = m_creatorMap[strKey]; std::function<I* (Ts...)> function = resolver.AnyCast<std::function<I* (Ts...)>>(); return function(Args...); } template <class I, typename... Ts> std::shared_ptr<I> ResolveShared(string strKey, Ts... Args) { auto b = Resolve<I, Ts...>(strKey, Args...); return std::shared_ptr<I>(b); }private: template<typename I, typename T, typename... Ts> struct Construct { static I invoke(Ts... Args) { return I(new T(Args...)); } };void RegisterType(string strKey, Any constructor) { if (m_creatorMap.find(strKey) != m_creatorMap.end()) throw std::logic_exception('this key has already exist!'); m_creatorMap.insert(make_pair(strKey, constructor)); }private: unordered_map<string, Any> m_creatorMap;};

使用说明:

类型注册分成三种方式注册,一种是简单方式注册,它只需要具体类型信息和key,类型的构造函数中没有参数,从容器中取也只需要类型和key;另外一种简单注册方式需要接口类型和具体类型,返回实例时,可以通过接口类型和key来得到具体对象;第三种是构造函数中带参数的类型注册,需要接口类型、key和参数类型,获取对象时需要接口类型、key和参数。返回的实例可以是普通的指针也可以是智能指针。需要注意的是key是唯一的,如果不唯一,会产生一个断言错误,推荐用类型的名称作为key,可以保证唯一性,std::string strKey = typeid(T).name()。

由于用到了C++11的可变模板参数,所以对编译器有要求,windows中需要vs2012的Microsoft Visual C++ Compiler Nov 2012 CTP;linux GCC4.7及以上。

测试代码:

struct ICar{        virtual ~ICar(){}        virtual void test() const = 0;};struct Bus : ICar{        Bus(int i, float f) {};        void test() const { std::cout << 'Bus::test()'; }};class IX{public:    IX(){}    virtual ~IX(){}    virtual void g()=0;private:};class X : public IX{public:  void g()   {    std::cout << 'it is a test' << std::endl;  }};    void TestMyIoc(){        //简单注册,需要类型信息和key    IocContainer ioc;    ioc.RegisterType<X>('ss');    ioc.RegisterType<X>('ss');//key重复,会报错    auto ix = ioc.ResolveShared<X>('ss');    ix->g();        //简单注册,需要类型信息、接口类型和key    ioc.SimpleRegisterType<IX, X>('ff');    auto ix1 = ioc.ResolveShared<IX>('ff');    ix1->g();        //含参数的类型注册,需要类型信息、接口类型、参数类型和key    ioc.RegisterType<ICar, Bus, int, float>('bus');    int a=1;    float b= 2.0;    auto mycar = ioc.ResolveShared<ICar>('bus', a, b);    mycar->test();}    

测试结果:

it is a testit is a testBus::test()

 补充一点:当resolve的参数类型为指针类型时,直接将nullptr作为参数传入会报异常,应该讲nullptr强制转换为注册时的参数类型。

ioc.Resolve<BaseAppChain>(str, (BaseAppChain*)nullptr);

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Unity依赖注入使用详解
C++标准库bitset类型的存储方式
C++中的size
C :后现代的系统编程语言 | 程序师
C++17新属性详解
IoC容器Autofac(5) - Autofac在Asp.net MVC Filter中的应用
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服