我写的这一个Console Framework是一个简单的带参数的控制台程序的基本框架,如果有很好的建议,欢迎大家拍砖!
这简单的框架主要包括以下几个部分:
1)Error的定义和管理,可以参考我的另一篇bolg http://jacky-dai.iteye.com/admin/blogs/1306613
2)Command Handler的定义和实现;
3)Function Dispatcher的实现;
4) main函数的构建;
看明白这个例子之后,以后只要需要些console app的地方可以直接试用,只要针对不同的Command添加XXhandler, 然后再添加到Dispatcher中去,最后再main中支持相对应的Command
ErrorCode框架定义
/**************************************************************************************************/ /*! \file CommonErrors.h \attention (c) Jacky Dai 2011~2016 All Rights Reserved. */ /**************************************************************************************************/ #ifndef XX_COMMON_ERRORS_H #define XX_COMMON_ERRORS_H /*** Include Files ********************************************************************************/ /*** Defines/Macros/Constants/Typedefs ************************************************************/ namespace CommonErrorSpace { //basic mask code const unsigned int COMPONENT_MASK = 0x8000; //component code const unsigned int COMPONENT_LOGIN = 0x0001; const unsigned int COMPONENT_DATAMANAGER = 0x0002; // //0x0000XXXX:XXXX means component code //0xXXXX0000:XXXX means error code of component //Define some marcos/functions here #define SYSTEM_ERROR_FLAG (0x4000) #define SYSTEM_ERROR(code) ((code | SYSTEM_ERROR_FLAG) << 16) #define ERROR_IS_SYSTEM_ERROR(err) (((err >> 16) & SYSTEM_ERROR_FLAG) != 0) #define COMPONENT_ERROR(component, code) ((code << 16) | (component & ~(COMPONENT_MASK))) #define CODE_FROM_ERROR(err) (static_cast<short>(err >> 16)) //All of the error code is here typedef enum { // Hex | Decimal | Descriptio //Basic error ERR_OK = 0x00000000, //<< 0x00000000 | 0 | No error. ERR_SYSTEM = SYSTEM_ERROR(1), //<< 0x00010000 | 65536 | General system error. ERR_TIMEOUT = SYSTEM_ERROR(2), //<< 0x00020000 | 131072 | Time out. //login component LOGIN_ERROR_UNKNOWN_ERROR = COMPONENT_ERROR(COMPONENT_LOGIN, 1), //<< 0x00010001 |65537 | Unrecognized error. LOGIN_ERROR_UNKNOWN_USER_NAME = COMPONENT_ERROR(COMPONENT_LOGIN, 2), //<< 0x00020001 |131073 | Unrecognized user name, it is case sensitive. //data manager component DATAMANAGER_ERROR_UNKNOWN_ERROR = COMPONENT_ERROR(COMPONENT_DATAMANAGER, 1), //<< 0x00010002 |65538 | Unrecognized error. DATAMANAGER_ERROR_MISSING_CONNECTION = COMPONENT_ERROR(COMPONENT_DATAMANAGER, 2) //<< 0x00020002 |131074 | Connection missed. } CommonError; /**************************************************************************************************/ /*! \class ErrorHelper Class with commands for translating error codes to useful strings. */ /**************************************************************************************************/ class ErrorHelper { public: static const char* getErrorName(CommonError error); static const char* getErrorDescription(CommonError error); }; } // CommonErrorSpace #endif //XX_COMMON_ERRORS_H
/**************************************************************************************************/ /*! \file CommonErrors.cpp \attention (c) Jacky Dai 2011~2016 All Rights Reserved. */ /**************************************************************************************************/ /*** Include Files ********************************************************************************/ #include "CommonErrors.h" /*** Defines/Macros/Constants/Typedefs ************************************************************/ namespace CommonErrorSpace { /*** Public Methods ******************************************************************************/ const char* ErrorHelper::getErrorName(CommonError error) { const char* result = "UKNOWN"; switch (error) { case ERR_OK: result = "ERR_OK"; break; case ERR_SYSTEM: result = "ERR_SYSTEM"; break; case ERR_TIMEOUT: result = "ERR_TIMEOUT"; break; case LOGIN_ERROR_UNKNOWN_ERROR: result = "LOGIN_ERROR_UNKNOWN_ERROR"; break; case LOGIN_ERROR_UNKNOWN_USER_NAME: result = "LOGIN_ERROR_UNKNOWN_USER_NAME"; break; case DATAMANAGER_ERROR_UNKNOWN_ERROR: result = "DATAMANAGER_ERROR_UNKNOWN_ERROR"; break; case DATAMANAGER_ERROR_MISSING_CONNECTION: result = "DATAMANAGER_ERROR_MISSING_CONNECTION"; break; default: break; } return result; } const char* ErrorHelper::getErrorDescription(CommonError error) { const char *result = "UKNOWN"; switch (error) { case ERR_OK: result = "No error."; break; case ERR_SYSTEM: result = "General system error."; break; case ERR_TIMEOUT: result = "Time out."; break; case LOGIN_ERROR_UNKNOWN_ERROR: result = "Unrecognized error."; break; case LOGIN_ERROR_UNKNOWN_USER_NAME: result = "Unrecognized user name, it is case sensitive."; break; case DATAMANAGER_ERROR_UNKNOWN_ERROR: result = "Unrecognized error."; break; case DATAMANAGER_ERROR_MISSING_CONNECTION: result = "Connection missed."; break; default: break; } return result; } } // CommonErrorSpace
Command Handler
/**************************************************************************************************/ /*! \file CommonHandler.h \attention (c) Jacky Dai 2011~2016 All Rights Reserved. */ /**************************************************************************************************/ #ifndef COMMAND_HANDLER_H #define COMMAND_HANDLER_H #include <windows.h> #include <string> #include "CommonErrors.h" using namespace std; using namespace CommonErrorSpace; // ////////////////////////////////////////////////////////////////////// class HandlerBase { public: HandlerBase(){} virtual ~HandlerBase(){}; virtual CommonError Parser(LPCSTR lpCommand) = 0; virtual VOID ShowInfo() = 0; virtual VOID HelpInfo(BOOL bDetail) = 0; protected: // VOID CatchError(string strMsg) // { // cout << "\nError!" << endl; // cout << strMsg.c_str() << endl; // } // // VOID GetAPIErrorInfo(CommonErrorSpace::CommonError errorCode) // { // cout << "\nError!\nCall " << m_strFuncName << "Failed!" << endl; // cout << "ErrorCode = 0x" << setw(8) << setfill('0') << hex << errorCode << endl; // cout << CommonErrorSpace::ErrorHelper::getErrorName(errorCode) << endl; // cout << CommonErrorSpace::ErrorHelper::getErrorDescription(errorCode) << endl; // } protected: string m_strFuncName; }; //AlgorithmType ////////////////////////////////////////////////////////////////////// class LoginHandler : public HandlerBase { public: typedef enum { ERR_OK = CommonErrorSpace::ERR_OK, ERR_SYSTEM = CommonErrorSpace::ERR_SYSTEM, ERR_TIMEOUT = CommonErrorSpace::ERR_TIMEOUT, LOGIN_ERROR_UNKNOWN_ERROR = CommonErrorSpace::LOGIN_ERROR_UNKNOWN_ERROR, LOGIN_ERROR_UNKNOWN_USER_NAME = CommonErrorSpace::LOGIN_ERROR_UNKNOWN_USER_NAME } Errors; LoginHandler(string strFuncName = "Login") { m_strFuncName = strFuncName; } virtual CommonError Parser(LPCSTR lpCommand); virtual VOID HelpInfo(BOOL bDetail); virtual VOID ShowInfo(); private: void Login(); private: string m_strUserName; string m_strUserPwd; }; //////////////////////////////////////////// class DataManagerHandler : public HandlerBase { public: typedef enum { ERR_OK = CommonErrorSpace::ERR_OK, ERR_SYSTEM = CommonErrorSpace::ERR_SYSTEM, ERR_TIMEOUT = CommonErrorSpace::ERR_TIMEOUT, DATAMANAGER_ERROR_UNKNOWN_ERROR = CommonErrorSpace::DATAMANAGER_ERROR_UNKNOWN_ERROR, DATAMANAGER_ERROR_MISSING_CONNECTION = CommonErrorSpace::DATAMANAGER_ERROR_MISSING_CONNECTION } Errors; DataManagerHandler(string strFuncName = "DataManager") { m_strFuncName = strFuncName; } virtual CommonError Parser(LPCSTR lpCommand); virtual VOID ShowInfo(); virtual VOID HelpInfo(BOOL bDetail); private: void DataManager(); private: string m_strDmName; string m_strDmPort; }; #endif//COMMAND_HANDLER_H
#include "CommandHandler.h" #include<algorithm> #include <iostream> using namespace std; //Login //////////////////////////////////////////// CommonError LoginHandler::Parser(LPCSTR lpCommand) { CommonErrorSpace::CommonError error = static_cast<CommonErrorSpace::CommonError>(ERR_OK); if (NULL == lpCommand) { HelpInfo(TRUE); error = static_cast<CommonErrorSpace::CommonError>(ERR_SYSTEM); cout << ErrorHelper::getErrorName(error) << endl; cout << ErrorHelper::getErrorDescription(error) << endl; return error; } else { string strCommand = lpCommand; string strBKCommand = lpCommand; transform(strCommand.begin(),strCommand.end(),strCommand.begin(), tolower); //Get Param1 ///////////////////////////////////////////////////////////////////////////////////// size_t nTypePos = strCommand.find("name="); size_t nOffSet = 5; if (nTypePos != string::npos) { size_t nCommaPos = strCommand.find_first_of(',', nTypePos); if (nCommaPos != string::npos) { m_strUserName = strBKCommand.substr(nTypePos+nOffSet, nCommaPos-nTypePos-nOffSet); } else { m_strUserName = strBKCommand.substr(nTypePos+nOffSet); } } else { HelpInfo(TRUE); error = static_cast<CommonErrorSpace::CommonError>(LOGIN_ERROR_UNKNOWN_USER_NAME); cout << ErrorHelper::getErrorName(error) << endl; cout << ErrorHelper::getErrorDescription(error) << endl; return error; } //Get Param2 ////////////////////////////////////////////////////////////////////////// nTypePos = strCommand.find("password="); nOffSet = 9; if (nTypePos != string::npos) { size_t nCommaPos = strCommand.find_first_of(',', nTypePos); if (nCommaPos != string::npos) { m_strUserPwd = strBKCommand.substr(nTypePos+nOffSet, nCommaPos-nTypePos-nOffSet); } else { m_strUserPwd = strBKCommand.substr(nTypePos+nOffSet); } } else { HelpInfo(TRUE); error = static_cast<CommonErrorSpace::CommonError>(LOGIN_ERROR_UNKNOWN_ERROR); cout << ErrorHelper::getErrorName(error) << endl; cout << ErrorHelper::getErrorDescription(error) << endl; return error; } Login(); //All parameters are ok, try to call local API ShowInfo(); cout << ErrorHelper::getErrorName(error) << endl; cout << ErrorHelper::getErrorDescription(error) << endl; return static_cast<CommonErrorSpace::CommonError>(error); } } VOID LoginHandler::HelpInfo(BOOL bDetail) { transform(m_strFuncName.begin(), m_strFuncName.end(), m_strFuncName.begin(), toupper); if (!bDetail) { cout << m_strFuncName.c_str() << " Login the server."; } else { cout << '\n' << m_strFuncName.c_str() << endl; cout << " [Name=#NAME]" << endl; cout << " [NAME] User name for server" << endl; cout << " [Password=#PWD]" << endl; cout << " [PWD] User password for server" << endl; } } VOID LoginHandler::ShowInfo() { cout << "\nSucceed!\n" << endl; cout << "\nRSP==>\n"; cout << "Login = {" << endl; cout << " name = " << m_strUserName.c_str() << endl; cout << " password = " << m_strUserPwd.c_str() << endl; cout << "}" << endl; } void LoginHandler::Login() { cout << "Do login state......\n"; } //DataManager ////////////////////////////////////////////////////////////////////////// CommonError DataManagerHandler::Parser(LPCSTR lpCommand) { CommonErrorSpace::CommonError error = static_cast<CommonErrorSpace::CommonError>(ERR_OK); if (NULL == lpCommand) { HelpInfo(TRUE); error = static_cast<CommonErrorSpace::CommonError>(ERR_SYSTEM); cout << ErrorHelper::getErrorName(error) << endl; cout << ErrorHelper::getErrorDescription(error) << endl; return error; } else { string strCommand = lpCommand; string strBKCommand = lpCommand; transform(strCommand.begin(),strCommand.end(),strCommand.begin(), tolower); //Get Param1 ///////////////////////////////////////////////////////////////////////////////////// size_t nTypePos = strCommand.find("name="); size_t nOffSet = 5; if (nTypePos != string::npos) { size_t nCommaPos = strCommand.find_first_of(',', nTypePos); if (nCommaPos != string::npos) { m_strDmName = strBKCommand.substr(nTypePos+nOffSet, nCommaPos-nTypePos-nOffSet); } else { m_strDmName = strBKCommand.substr(nTypePos+nOffSet); } } else { HelpInfo(TRUE); error = static_cast<CommonErrorSpace::CommonError>(ERR_TIMEOUT); cout << ErrorHelper::getErrorName(error) << endl; cout << ErrorHelper::getErrorDescription(error) << endl; return error; } //Get Param2 ////////////////////////////////////////////////////////////////////////// nTypePos = strCommand.find("port="); nOffSet = 5; if (nTypePos != string::npos) { size_t nCommaPos = strCommand.find_first_of(',', nTypePos); if (nCommaPos != string::npos) { m_strDmPort = strBKCommand.substr(nTypePos+nOffSet, nCommaPos-nTypePos-nOffSet); } else { m_strDmPort = strBKCommand.substr(nTypePos+nOffSet); } } else { HelpInfo(TRUE); error = static_cast<CommonErrorSpace::CommonError>(DATAMANAGER_ERROR_MISSING_CONNECTION); cout << ErrorHelper::getErrorName(error) << endl; cout << ErrorHelper::getErrorDescription(error) << endl; return error; } DataManager(); //All parameters are ok, try to call local API ShowInfo(); cout << ErrorHelper::getErrorName(error) << endl; cout << ErrorHelper::getErrorDescription(error) << endl; return error; } } VOID DataManagerHandler::ShowInfo() { cout << "\nSucceed!\n" << endl; cout << "\nRSP==>\n"; cout << "DataManager = {" << endl; cout << " Name = " << m_strDmName.c_str() << endl; cout << " Port = " << m_strDmPort.c_str() << endl; cout << "}" << endl; } VOID DataManagerHandler::HelpInfo(BOOL bDetail) { transform(m_strFuncName.begin(), m_strFuncName.end(), m_strFuncName.begin(), toupper); if (!bDetail) { cout << m_strFuncName.c_str() << " Connect to Data server."; } else { cout << '\n' << m_strFuncName.c_str() << endl; cout << " [Name=#NAME]" << endl; cout << " [NAME] Data server name" << endl; cout << " [Port=#PORT]" << endl; cout << " [PORT] Data server port" << endl; } } void DataManagerHandler::DataManager() { cout << "Do data manager......\n"; }
Function Dispatcher
/**************************************************************************************************/ /*! \file FuncDispatcher.h \attention (c) Jacky Dai 2011~2016 All Rights Reserved. */ /**************************************************************************************************/ #ifndef FUNC_DISPATCHER_H #define FUNC_DISPATCHER_H #include <map> #include "CommandHandler.h" using namespace std; typedef map<string, HandlerBase*> Dispatcher; class FuncDispatcher { public: FuncDispatcher(); ~FuncDispatcher(); VOID Init(); VOID Clear(); VOID ShowHelpInfo(BOOL bDetailInfo); HandlerBase* FindHandler(LPCSTR lpFuncName); private: Dispatcher m_Dispatcher; }; #endif//FUNC_DISPATCHER_H
#include "FuncDispatcher.h" #include "CommandHandler.h" #include <iostream> using namespace std; FuncDispatcher::FuncDispatcher() { Init(); } FuncDispatcher::~FuncDispatcher() { Clear(); } VOID FuncDispatcher::Init() { m_Dispatcher.insert(make_pair("login", new LoginHandler())); m_Dispatcher.insert(make_pair("datamanager", new DataManagerHandler())); } VOID FuncDispatcher::Clear() { Dispatcher::const_iterator iter = m_Dispatcher.begin(); Dispatcher::const_iterator end = m_Dispatcher.end(); for ( ; iter!=end; ++iter) { delete iter->second; } m_Dispatcher.clear(); } VOID FuncDispatcher::ShowHelpInfo(BOOL bDetailInfo) { Dispatcher::const_iterator iter = m_Dispatcher.begin(); Dispatcher::const_iterator end = m_Dispatcher.end(); for ( ; iter!=end; ++iter) { iter->second->HelpInfo(bDetailInfo); cout << endl; } } HandlerBase* FuncDispatcher::FindHandler(LPCSTR lpFuncName) { if (NULL==lpFuncName) { return NULL; } string strTemp = lpFuncName; Dispatcher::const_iterator item = m_Dispatcher.find(lpFuncName); if (item == m_Dispatcher.end()) { return NULL; } else { return item->second; } return NULL; }
main函数
/*************************************************************************************************/ /*! \file main.cpp \ Author : Jacky Dai \ Version : Ver 1.0.0.0 \ Date : 2016-07-11 \ Copyright : All Rights Reserved. \ Description : \Usage : */ /*************************************************************************************************/ #include "FuncDispatcher.h" #include<algorithm> #include <iostream> using namespace std; const string STR_HELP_API = "help"; const string STR_LOGIN_API = "login"; const string STR_DATA_MANAGER_API = "datamanager"; FuncDispatcher g_FuncDispatcher; ////////////////////////////////////////////////////////////////////////// int main(int argc, char** argv) { if (1 == argc) { //There is no command, so do nothing. cout << "Do nothing!" << endl; return 0; } else { //TODO //Load default parameters } for(int argIndex = 1; argIndex < argc; ++argIndex) { HandlerBase* pCommandHandler = NULL; string strCommandName = argv[argIndex]; string strBKCommandName = argv[argIndex]; transform(strCommandName.begin(),strCommandName.end(),strCommandName.begin(), tolower); if (STR_HELP_API == strCommandName) { if (2 == argc) //Show all help info { cout << '\n'; g_FuncDispatcher.ShowHelpInfo(FALSE); } else if (3 == argc) //Show single API help info { strCommandName = argv[argc-1]; strBKCommandName = argv[argc-1]; transform(strCommandName.begin(),strCommandName.end(),strCommandName.begin(), tolower); pCommandHandler = g_FuncDispatcher.FindHandler(strCommandName.c_str()); if (pCommandHandler != NULL) { pCommandHandler->HelpInfo(TRUE); } else { cout << "\n\"" << strBKCommandName << "\"" << " is not a supported command!" << endl; return -1; } } else { cout << "\nHelp [CMD]" << endl; cout << "[CMD] Show detail help information for the command." << endl; return -1; } return 0; } else { pCommandHandler = g_FuncDispatcher.FindHandler(strCommandName.c_str()); if (NULL == pCommandHandler) { cout << "\n\"" << strBKCommandName << "\" is a invalid Command!" << endl; return -1; } if (STR_LOGIN_API==strCommandName || STR_DATA_MANAGER_API==strCommandName) { if (argc >= 3) { argIndex++; strCommandName = argv[argIndex]; strBKCommandName = argv[argIndex]; pCommandHandler->Parser(strCommandName.c_str()); break; } else { pCommandHandler->Parser(NULL); //Means the API does not contains parameters break; } } else if (pCommandHandler != NULL) { //other commands pCommandHandler->ShowInfo(); break; } else { cout << "Unknown Exception!" << endl; return -1; } } } return 0; }
测试脚本
@ECHO OFF ECHO -------------------Unit Test for "Help" Command----------------------- TITLE "Help" Command Test. REM ///////////////////////////////////////////////////////////////////////////////// ECHO -- Case 1:Call all help info ECHO -- Expected Resut: Show all API help info REM Show all API help info REM --------------------------------------------------------------------------------- ECHO COMMAND:ConsoleFrameworkDemo Help ConsoleFrameworkDemo Help IF "%1" == "" PAUSE REM ///////////////////////////////////////////////////////////////////////////////// ECHO -- Case 2:Call help info of Login ECHO -- Expected Resut: Show all Login help info REM Show all login help info REM --------------------------------------------------------------------------------- ECHO COMMAND:ConsoleFrameworkDemo Help Login ConsoleFrameworkDemo Help login IF "%1" == "" PAUSE REM ///////////////////////////////////////////////////////////////////////////////// ECHO -- Case 3:Call help info of DataManager ECHO -- Expected Resut: Show all DataManager help info REM Show all datamanager help info REM --------------------------------------------------------------------------------- ECHO COMMAND:ConsoleFrameworkDemo Help DataManager ConsoleFrameworkDemo Help DataManager IF "%1" == "" PAUSE
@ECHO OFF ECHO -------------------Unit Test for "Login" Command----------------------- TITLE "Login" Command Test. REM ///////////////////////////////////////////////////////////////////////////////// ECHO -- Case 1:Does no pass any parameters for Login API ECHO -- Expected Resut: Show Login usge info REM Show Login usge info REM --------------------------------------------------------------------------------- ECHO COMMAND:ConsoleFrameworkDemo Login ConsoleFrameworkDemo Login IF "%1" == "" PAUSE REM ///////////////////////////////////////////////////////////////////////////////// ECHO -- Case 2:pass one parameter for Login API ECHO -- Expected Resut: Show Login usge info REM Show Login usge info REM --------------------------------------------------------------------------------- ECHO COMMAND:ConsoleFrameworkDemo Login Name="Jacky" ConsoleFrameworkDemo Login Name="Jacky" IF "%1" == "" PAUSE REM ///////////////////////////////////////////////////////////////////////////////// ECHO -- Case 3:pass two parameters for Login API ECHO -- Expected Resut: Should handler it well REM Should handler it well REM --------------------------------------------------------------------------------- ECHO COMMAND:ConsoleFrameworkDemo Login Name="Jacky",Password="123" ConsoleFrameworkDemo Login Name="Jacky",Password="123" IF "%1" == "" PAUSE
@ECHO OFF ECHO -------------------Unit Test for "DataManager" Command----------------------- TITLE "DataManager" Command Test. REM ///////////////////////////////////////////////////////////////////////////////// ECHO -- Case 1:Does no pass any parameters for DataManager API ECHO -- Expected Resut: Show DataManager usge info REM Show DataManager usge info REM --------------------------------------------------------------------------------- ECHO COMMAND:ConsoleFrameworkDemo DataManager ConsoleFrameworkDemo DataManager IF "%1" == "" PAUSE REM ///////////////////////////////////////////////////////////////////////////////// ECHO -- Case 2:pass one parameter for DataManager API ECHO -- Expected Resut: Show DataManager usge info REM Show DataManager usge info REM --------------------------------------------------------------------------------- ECHO COMMAND:ConsoleFrameworkDemo DataManager Name="Jacky" ConsoleFrameworkDemo DataManager Name="Jacky" IF "%1" == "" PAUSE REM ///////////////////////////////////////////////////////////////////////////////// ECHO -- Case 3:pass two parameters for DataManager API ECHO -- Expected Resut: Should handler it well REM Should handler it well REM --------------------------------------------------------------------------------- ECHO COMMAND:ConsoleFrameworkDemo DataManager Name="Jacky",Port="123" ConsoleFrameworkDemo DataManager Name="Jacky",Port="123" IF "%1" == "" PAUSE