使用Autumn框架进行C++依赖注入示例

Posted sunny_ss12

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Autumn框架进行C++依赖注入示例相关的知识,希望对你有一定的参考价值。

项目中用到了Autumn,看到了一篇简介的文章,记录在这。

转载自:http://blog.csdn.net/logsharp/article/details/1726024  《无他,唯程序尔》该博主好像就是Autumn的作者

1.1.  Autumn简介

Autumn Framework是一个C++的依赖注入(DI)框架,它的功能是模仿JAVA领域中的Spring框架来的。当前只是提供依赖注入功能,而且尽量做到对原代码的不侵入。因为C++没有象JAVA那样的动态反射机制,不能很容易地在运行时得到注入的一些相关信息,所以在使用Autumn的时候,需要做一些工作来让Autumn框架知道注入时所需要的一些信息,即使用Autumn自带的一个工具AutumnGen来生成一些Wrapper文件。

通过使用Autumn,可以将动态库很容易地跟原来的程序部署在一起,而不需要重新编译原有程序。

Autumn可以从这儿下载并编译,当前最新版本是0.5.0。

1.2.  Autumn示例

例子很简单。文件Action.h中定义了一个接口Action,如下:

class Action

public:

    virtual string excute(const char* s) = 0;

;

对该接口做一些不同的实现,然后在我们的程序中调用。

1.2.1.  不使用Autumn的开发过程

我们在文件LowerAction.h中对接口做一个实现LowerAction(因为比较简单,所以没有写.cpp文件),如下:

class LowerAction: public Action

private:

    string Message;

 

public:

    LowerAction(const char* msg)

        this->Message = msg;

    

 

    string excute(const char* s)

        string r = this->Message + ", " + s;

        for( int i = 0; i < r.length(); i++)

            r[i] = tolower(r[i]);

 

        return r;

    

;

在文件UpperAction.h中对接口做另一个新的实现UpperAction,如下:

class UpperAction: public Action

private:

    string Message;

 

public:

    void  setMessage(const char* msg)

        this->Message = msg;

    

 

    string excute(const char* s)

        string r = this->Message + ", " + s;

        for( int i = 0; i < r.length(); i++)

            r[i] = toupper(r[i]);

 

        return r;

    

;

 

现在写主程序。

开始我们想调用LowerAction这个实现:

#include <iostream>

#include "Action.h"

#include "LowerAction.h"

 

int main(int argc, char* argv[])

    Action* pa = new LowerAction(“Hello”);

    cout<<pa->excute("Vincent")<<endl;

    delete pa ;

 

    return 0;

在主程序中,为LowerAction传入构造参数。编译主程序后,可得到运行结果:

hello, vincent

 

后来,我们想调用UpperAction这个实现,我们需要修改主程序如下

#include <iostream>

#include "Action.h"

#include "UpperAction.h"

 

int main(int argc, char* argv[])

    UpperAction* pua = new UpperAction();

    pua->setMessage("Hello");

 

    Action* pa = pua;

    cout<<pa->excute("Vincent")<<endl;

    delete pa;

 

    return 0;

在主程序中需要为UpperAction的实例设置属性Message。编译主程序后可得到运行结果

       HELLO, VINCENT

 

当想换用不同的实现时,我们需要做以下几项工作:

w          修改主程序(原来是要new一个LowerAction,后来要new一个UpperAction);

w          为不同的实现进行实例化相关的一些操作,比如设置属性;

w          重新编译程序。

1.2.2.  使用Autumn的开发过程

Autumn框架尽量做到对原来代码不侵入,所以,使用Autumn框架时,接口文件Action.h及实现文件LowerAction.hUpperAction.h都不需要修改。使用Autumn开发,大概有如下五个步骤。

1.2.2.1.  生成Wrapper文件

为那些需要Autumn来操作的类(主要是那些用来注入或被注入的类)生成Wrapper。使用AutumnGen可以根据C++的头文件自动生成相关的Wrapper文件。在本示例中为LowerActionUpperAction生成Wrapper,命令如下:

AutumnGen LowerAction.h UpperAction.h

执行后生成四个文件:LowerAction_Wrapper.hLowerAction_Wrapper.cppUpperAction_Wrapper.hUpperAction_Wrapper.cpp

1.2.2.2.  生成动态库

Autumn主要是基于动态库来实现灵活的依赖注入的。我们要把需要Autumn来操作的类及其Wrapper编译到一个动态库中。在本示例中,我们将实现LowerActionUpperAction及其Wrapper都编译到一个动态库ActionImpl.dll中。

1.2.2.3.  编写配置文件

实现类都存在于ActionImpl.dll中,我们想让其提供LowerAction的实现,可以编写如下一个配置文件autumnDemo.xml

<?xml version="1.0" encoding="UTF-8"?>

<autumn>

    <library path="../lib/ActionImpl.dll" name="ActionImpl">

        <beans>

            <bean class="LowerAction" name="TheAction">

                <constructor-arg>

                    <argument>

                        <value>Hello</value>

                    </argument>

                </constructor-arg>

            </bean>

        </beans>

    </library>

</autumn>

Autumn的配置文件采用XML格式,相应的schema文件autumn.xsd在源码包中。本配置文件中指出了动态库的路径(../lib/ActionImpl.dll),实现类的类名(LowerAction),实现类在Autumn中的命名(TheAction),实现类的构造参数(”Hello”)等内容。

1.2.2.4.  编写主程序

主程序中使用AutumnBeanFactory来取得想使用的实现类,调用其excute方法。程序如下:

#include <iostream>

#include <exception>

#include "Action.h"

#include "IBeanFactory.h"

 

using namespace std;

 

int main(int argc, char* argv[])

    try

        Autumn::IBeanFactory* bf;

 

        bf = Autumn::getBeanFactoryWithXML("autumnDemo.xml");

        Action* pa = (Action*)bf->getBean("TheAction");

 

        cout<<pa->excute("Vincent")<<endl;

 

        bf->freeBean(pa);

        Autumn::deleteBeanFactory(bf);

    catch (const exception& e )

        cout<<"Exception: "<<e.what()<<endl;

    

    return 0;

主程序中首先取得BeanFactory,然后调用其getBean方法来取得实现类,用完之后,通过其freeBean来释放该实现类,程序最后释放BeanFactoryAutumn框架中的接口都在名字空间Autumn中。程序编译时需要连接Autumn框架的库文件AutumnFramework.lib(在非Windows平台上是libAutumn.so)。

按照上面1.2.2.3. 中的配置文件,使用的实现类是LowerAction,运行主程序,结果如下:

       hello, vincent

1.2.2.5.  换用不同的实现

如果想不用LowerAction,而去使用UpperAction这个实现,可以修改配置文件如下:

<?xml version="1.0" encoding="UTF-8"?>

<autumn>

    <library path="../lib/ActionImpl.dll" name="ActionImpl">

        <beans>

            <bean class="UpperAction" name="TheAction">

                <properties>

                    <property name="Message" type="char*">

                        <value>Hello</value>

                    </property>

                </properties>

            </bean>

        </beans>

    </library>

</autumn>

保存配置文件后,不需要重新编译任何程序,直接运行主程序,结果如下:

       HELLO, VINCENT

如果想更改实现类的属性值,也不需要修改程序,只需要修改Autumn的配置文件即可。修改LowerAction的属性值,只要修改配置文件中的构造参数即可,如把Hello改为Hi;同样如果想修改UpperAction的属性值,只要修改配置文件中它的名字为Message的属性的值即可。

 从这儿下载示例源代码


以上是关于使用Autumn框架进行C++依赖注入示例的主要内容,如果未能解决你的问题,请参考以下文章

使用Ninject进行DI(依赖注入)

详解.NET Core 依赖注入生命周期

别把Java写成C++的样子。你真的在正确运用依赖注入吗?

使用 .NET Core 进行 Hangfire 依赖注入

Play 框架依赖注入

.NET Core Web API使用依赖注入(DI)进行服务配置一