最近在做的WINCE程序即将送测,客户端有很多东西都要移到配置文件中,于是惯性思维的我们想到了
System.Configuration.ConfigurationManager类。
一如既往的,我们添加个XML文件,重命名为
APP.CONFIG,
修改其中内容为
<?xml version=
"
1.0
"
encoding=
"
utf-8
"
?>
<configuration>
<appSettings>
<!--DeviceSvc地址-->
<add key =
"
DeviceSvcAddress
"
value=
"
http://***********/DeviceSvc.svc
"
/>
</appSettings>
</configuration>
保存之后,在调用的地方很顺其自然的 调用
var
filePath = ConfigurationManager.AppSettings[
"DeviceSvcAddress"
];
之后傻眼了,发现CompactFramework这个精简的.NET框架不支持ConfigurationManager,那怎么办,这种配置型的字符串不可能放在代码中啊。转念一想,其实ConfigurationManager无非也就是个XML文件读取类,CompactFramework对XML读写可是完全支持,那么为何我们不可以自己写一个。
动手之前可以先整理下需求,这个类要干什么:
1.最好是静态的,方便调用。
2.能读取APP。Config中的配置节点。
3.如果再能添加修改就更好了。
OK,需求确定那就动手
public
static
class
AppConfiger
{
public
static
string
_configName =
string
.Empty;
private
static
XDocument _configDoc =
null
;
private
static
string
_path =
string
.Empty;
static
AppConfiger()
{
//
编译CAB文件发布时要修改为
//
_configName = "Cp.Device.exe.Config";
//
正常调试时使用
//
#if DEBUG
//
_configName = "App.Config";
//
#endif
//
#if !DEBUG
//
_configName = "Cp.Device.exe.Config";
//
#endif
LoadConfigurationFile(_configName);
}
private static void LoadConfigurationFile(string configName)
{
_configDoc = new XDocument();
string appDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
_path = Path.Combine(appDir, configName);
_configDoc = XDocument.Load(_path);
}
}
这是这个类的一个属性跟构造函数,_configName 这个就是配置文件的文件名,大家注意这一段
//
编译CAB文件发布时要修改为
//
_configName = "Cp.Device.exe.Config";
//
正常调试时使用
//
#if DEBUG
//
_configName = "App.Config";
//
#endif
//
#if !DEBUG
//
_configName = "Cp.Device.exe.Config";
//
#endif
这一段弄得我好纠结,WINCE程序Deploye运行方式有2种,
一种是直连开发机,用VS的F5运行之后VS可以做一次发布,你可以修改程序的发布路径,这种方式中还有DEBUG跟RELEASE模式。由于某种我不知道的原因,这样的方式发布出来的文件,没有*.exe.config这样的配置文件生成,于是我把APP.CONFING属性改为Contant+copy always。之后就用app.config文件去读配置。
另外一种方式就是编译CAB包安装,这也是模拟正常发布的流程,这种方式下会生成*.exe.config这个文件,我以为这个模式也会有DEBUG跟RELEASE之分所以就用了
“#if DEBUG”
这样的编译路径去区分,结果发现无论什么方式编译出来的CAB包,都只会走到
_configName = "App.Config";
这个分支中,在程序发布时,如果有2个配置文件这种事情也太不专业了
,于是我就换了另外一种思路去读取配置文件
private
static
void
LoadConfigurationFile()
{
var
configName =
"
App.Config
"
;
_configDoc =
new
XDocument();
string
appDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase);
_path = Path.Combine(appDir, configName);
try
{
_configDoc = XDocument.Load(_path);
}
catch
(FileNotFoundException)
{
configName =
"
Cp.Device.exe.Config
"
;
_path = Path.Combine(appDir, configName);
_configDoc = XDocument.Load(_path);
}
catch
(Exception)
{
MessageBox.Show(
"
配置文件错误
"
);
return
;
}
}
这样就会在发布跟编译时都可以读取各自的CONFIG文件而不用每次都跑去修改_configName了。
既然我们已经拿到了_configDoc,其他就好说了:
对节点的一些操作
private
static
XElement GetDescendant(
string
key)
{
var
getAppSettings = _configDoc.Descendants(
"
appSettings
"
).Elements();
XElement elem =
null
;
foreach
(
var
setting
in
getAppSettings)
{
XAttribute keyAtt = setting.Attribute(
"
key
"
);
if
(keyAtt.Value == key)
{
elem = setting;
break
;
}
}
return
elem;
}
public
static
void
Add(
string
key,
string
Value)
{
LoadConfigurationFile();
//
LoadConfigurationFile(_configName);
XElement element =
new
XElement(
"
add
"
,
new
XAttribute(
"
key
"
, key),
new
XAttribute(
"
value
"
, Value));
var
addElement = _configDoc.Descendants(
"
appSettings
"
).Elements().Last();
addElement.AddAfterSelf(element);
_configDoc.Save(_path);
}
public
static
string
GetAppSettingValue(
string
key)
{
XElement getAppSettings = GetDescendant(key);
var
configValue = getAppSettings.Attribute(
"
value
"
).Value;
return
configValue.ToString();
}
public
static
void
SetAppSettingValue(
string
key,
string
newValue)
{
XElement getAppSettings = GetDescendant(key);
getAppSettings.SetAttributeValue(
"
value
"
, newValue);
_configDoc.Save(_path);
}
调用的时候也很简单
var i = AppConfiger.GetAppSettingValue("DeviceSvcAddress");
至此,我们自己写的可以用在CompactFramework中的Confier已经完成了。
Wince自定义的ConfigurationManager