80570096 2011-11-24
在前一篇文章中,大家可能都注意到了一个细节,Ice的初始化函数initialize的输入参数正好是主函数的输入参数,也就是命令行参数(注:辅助类Ice::Application也调用了initialize函数)。
Ice的初始化函数得到命令行参数后,抽取出Ice专有参数,并把分析后的配置存入到Ice的属性表中。
假设命令行为:
MyProg.exe--myoption--Ice.Config=config\
-xa--Ice.Trace.Network=3-yoptfile
其中MyProg.exe是我们用Ice编写的程序,当Ice::initialize返回时,Ice的两个专用参数就会被抽去,argc由原来的9变成7,argv为:
MyProg.exe
--myoption
-x
a
-y
opt
file
抽去的两个参数则存放于属性表里。属性表的类型为Ice::Properties,它的常用方法有:
std::stringgetProperty(conststd::string&prop);
std::stringgetPropertyWithDefault(conststd::string&prop,conststd::string&);
Ice::IntgetPropertyAsInt(conststd::string&prop);
Ice::IntgetPropertyAsIntWithDefault(conststd::string&prop,Ice::Int);
取得prop属性的值
Ice::StringSeqgetPropertyAsList(const::std::string&prop);
Ice::StringSeqgetPropertyAsListWithDefault(const::std::string&prop,const::Ice::StringSeq&);
取得prop属性的值,并返回按逗号分割成的一组值。这里的Ice::StringSeq就是std::vector<std::string>(注:集合类型可通过配置改变,默认是vector)。
比如:有命令行参数:--MyProp.Test=abc,def,aaa,sde,s则返回
abc
def
aaa
sde
s
Ice::PropertyDictgetPropertiesForPrefix(const::std::string&prefix);
返回所有含有prefix前缀的所有属性,PropertyDict是一个std::map<std::string,std::string>类型的数据表。
voidsetProperty(const::std::string&prop,const::std::string&);
设置prop属性的值
Ice::StringSeqgetCommandLineOptions();
把属性表中的所有数据转化成字符串列表
Ice::StringSeqparseCommandLineOptions(
conststd::string&prefix,constIce::StringSeq&args);
分析命令行参数,抽取出所有prefix前缀的参数,返回剩余的命令行参数。由于main函数输入的是argc和argv,我们可以使用Ice::StringSeqargsToStringSeq(int,char*[])和voidstringSeqToArgs(constStringSeq&,int&,char*[])函数在StringSeq与argc/argv之间互相转换。
Ice::StringSeqparseIceCommandLineOptions(constIce::StringSeq&);
分析Ice专有命令行参数
voidload(conststd::string&file);
载入file指定的配置文件,关于配置文件后文还会讲到
Ice::PropertiesPtrclone()
返回一个属性表的拷贝
下面是获得属性表的两个常用方式:
Ice::PropertiesPtrcreateProperties();
生成一个全新的属性表
Ice::PropertiesPtrIce::Communicator::getProperties();
从连接器中取得当前使用的属性表
利用属性表改进我们的程序
比如,我们前面的客户端的例子:
classMyApp:publicIce::Application{
public:
virtualintrun(int,char*[])
{
Ice::CommunicatorPtric=communicator();
Ice::ObjectPrxbase=
ic->stringToProxy("SimplePrinter:default-p10000");
PrinterPrxprinter=PrinterPrx::checkedCast(base);
if(!printer)throw"InvalidProxy!";
printer->printString("HelloWorld!");
return0;
}
};
ic->stringToProxy("SimplePrinter:default-p10000");这句把代理名、协议、端口以及主机名都固化在了程序中。有时,我们需要更大的灵活性,比如由命令行参数或配置文件指定它们,上面提到的Properties接口就可以帮我们:
classMyApp:publicIce::Application{
public:
virtualintrun(int,char*[])
{
Ice::CommunicatorPtric=communicator();
Ice::PropertiesPtrprop=ic->getProperties();
strings=prop->getPropertyWithDefault(
"Ice.Printer","SimplePrinter:default-p10000");
Ice::ObjectPrxbase=ic->stringToProxy(s);
PrinterPrxprinter=PrinterPrx::checkedCast(base);
if(!printer)throw"InvalidProxy!";
printer->printString("HelloWorld!");
return0;
}
};
这里,代理字符串从属性表(Ice::Properties,Ice::PropertiesPtr是Ice::Properties的智能指针)中得到,我们只要改变命令行参数就可以改变这个字符串,如:
MyProg.exe--Ice.Printer="SimplePrinter:tcp-p10000"
MyProg.exe--Ice.Printer="SimplePrinter:tcp-p1234-h192.168.1.5"
...
可能你已经猜到,如果命令行里没有指定Ice.Printer,则使用默认的"SimplePrinter:default-p10000"
另外,上面的:
Ice::PropertiesPtrprop=ic->getProperties();
strings=prop->getPropertyWithDefault(
"Ice.Printer","SimplePrinter:default-p10000");
Ice::ObjectPrxbase=ic->stringToProxy(s);
三条指令可以用一条指令代替:
Ice::ObjectPrxbase=ic->propertyToProxy("Ice.Printer");
多写几行有时还是有用的,我们可以利用它来读取我们自定义的一些参数^_^(当然还有默认参数功能)
上面的命令行里我们取的是"Ice.Printer"属性,注意它的前缀是"Ice.",如果我们改成其它前缀,如"MyProp.",那么Ice初始化时就不认为这是Ice专用参数而不理睬它了。
我们想自定义一些属性用于“私用”的话,使用"Ice."前缀就显得不合理了,这时我们可以使用属性集的parseCommandLineOptions方法来解析指定前缀的参数:
classMyApp:publicIce::Application{
public:
virtualintrun(intargc,char*argv[])
{
Ice::CommunicatorPtric=communicator();
Ice::PropertiesPtrprop=Ice::createProperties();
prop->parseCommandLineOptions("MyProp",
Ice::argsToStringSeq(argc,argv));
strings=prop->getPropertyWithDefault(
"MyProp.Printer","SimplePrinter:default-p10000");
Ice::ObjectPrxbase=ic->stringToProxy(s);
PrinterPrxprinter=PrinterPrx::checkedCast(base);
if(!printer)throw"InvalidProxy!";
printer->printString("HelloWorld!");
return0;
}
};
现在,程序可以解析MyProp.Printer属性了。
配置文件
对于少量的属性,使用命令行参数确实没什么问题,一旦自定义属性增加,使用命令行参数就显得不太合适了。
Ice允许我们把所有的属性参数写到一个文本文件里,每个参数一行,比如有:
MyProg.exe\
--MyProp.Printer="SimplePrinter:tcp-p1234-h192.168.1.5"\
--MyProp.Test="abc,def,aaa,sde,s"
我们可以生成一个文本文件,内容:
MyProp.Printer="SimplePrinter:tcp-p1234-h192.168.1.5"
MyProp.Test="abc,def,aaa,sde,s"
然后,把上面的命令行参数改成:
MyProg.exe--Ice.Config=文件名
或者使用Ice::Properties::load方法载入文件,
或者使用Ice::Properties::parseIceCommandLineOptions方法解析文本内容。