解决在Web.config或App.config中添加自定义配置的方法详解
程序员文章站
2024-03-02 21:24:04
.net中的system.configuration命名空间为我们在web.config或者app.config中自定义配置提供了完美的支持。最近看到一些项目中还在自定义x...
.net中的system.configuration命名空间为我们在web.config或者app.config中自定义配置提供了完美的支持。最近看到一些项目中还在自定义xml文件做程序的配置,所以忍不住写一篇用系统自定义配置的随笔了。
如果你已经对自定义配置了如指掌,请忽略这篇文章。
言归正传,我们先来看一个最简单的自定义配置
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configsections>
<section name="simple" type="configexample.configuration.simplesection,configexample"/>
</configsections>
<simple maxvalue="20" minvalue="1"></simple>
</configuration>
在配置文件中使用自定义配置,需要在configsections中添加一个section元素,并制定此section元素对应的类型和名字。然后再在configuration根节点下面添加此自定义配置,如上例中的simple节点。simple节点只有两个整形数的属性maxvalue和minvalue。
要在程序中使用自定义配置我们还需要实现存取这个配置块的类型,一般需要做如下三件事:
1. 定义类型从system.configuration.configurationsection继承
2. 定义配置类的属性,这些属性需要用configurationproperty特性修饰,并制定属性在配置节中的名称和其他一些限制信息
3. 通过基类的string索引器实现属性的get ,set
非常简单和自然,如下是上面配置类的实现:
public class simplesection:system.configuration.configurationsection
{
[configurationproperty("maxvalue",isrequired=false,defaultvalue=int32.maxvalue)]
public int maxvalue
{
get
{
return (int)base["maxvalue"];
}
set
{
base["maxvalue"] = value;
}
}
[configurationproperty("minvalue",isrequired=false,defaultvalue=1)]
public int minvalue
{
get { return (int) base["minvalue"];}
set { base["minvalue"] = value; }
}
[configurationproperty("enabled",isrequired=false,defaultvalue=true)]
public bool enable
{
get
{
return (bool)base["enabled"];
}
set
{
base["enabled"] = value;
}
}
}
这样子一个简单的配置类就完成了,怎么在程序中使用这个配置呢?需要使用configurationmanager类(要引用system.configuration.dll这个dll只有在.net2.0之后的版本中才有)的getsection方法获得配置就可以了。如下代码:
simplesection simple = configurationmanager.getsection("simple") as simplesection;
console.writeline("simple minvalue={0} maxvalue = {1}",simple.minvalue,simple.maxvalue);
这个配置类太过简陋了,可能有时候我们还需要更复杂的构造,比如在配置类中使用类表示一组数据,下面我们看一个稍微复杂一点的自定义配置
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configsections>
<section name="complex" type="configexample.configuration.complexsection,configexample"/>
</configsections>
<complex height="190">
<child firstname="james" lastname="bond"/>
</complex>
</configuration>
这个配置的名字是complex,他有一个属性height,他的节点内还有一个child元素这个元素有两个属性firstname和lastname;对于这个内嵌的节点该如何实现呢?首先我们需要定义一个类,要从configurationelement类继承,然后再用和simplesection类似的方法定义一些用configurationproperty特性修饰的属性就可以了,当然属性值的get,set也要使用基类的索引器。如下实现:
public class complexsection : configurationsection
{
[configurationproperty("height", isrequired = true)]
public int height
{
get
{
return (int)base["height"];
}
set
{
base["height"] = value;
}
}
[configurationproperty("child", isdefaultcollection = false)]
public childsection child
{
get
{
return (childsection)base["child"];
}
set
{
base["child"] = value;
}
}
}
public class childsection : configurationelement
{
[configurationproperty("firstname", isrequired = true, iskey = true)]
public string firstname
{
get
{
return (string)base["firstname"];
}
set
{
base["firstname"] = value;
}
}
[configurationproperty("lastname", isrequired = true)]
public string lastname
{
get
{
return (string)base["lastname"];
}
set
{
base["lastname"] = value;
}
}
}
还有稍微再复杂一点的情况,我们可能要在配置中配置一组相同类型的节点,也就是一组节点的集合。如下面的配置:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configsections>
<section name="complex" type="configexample.configuration.complexsection,configexample"/>
</configsections>
<complex height="190">
<child firstname="james" lastname="bond"/>
<children>
<add firstname="zhao" lastname="yukai"/>
<add firstname="lee" lastname="yukai"/>
<remove firstname="zhao"/>
</children>
</complex>
</configuration>
请看children节点,它就是一个集合类,在它里面定义了一组add元素,也可以有remove节点把已经添进去的配置去掉。
要使用自定义节点集合需要从configurationelementcollection类继承一个自定义类,然后要实现此类getelementkey(configurationelement element)和configurationelement createnewelement()两个方法;为了方便的访问子节点可以在这个类里面定义只读的索引器。请看下面的实现
public class children : configurationelementcollection
{
protected override object getelementkey(configurationelement element)
{
return ((childsection)element).firstname;
}
protected override configurationelement createnewelement()
{
return new childsection();
}
public childsection this[int i]
{
get
{
return (childsection)base.baseget(i);
}
}
public childsection this[string key]
{
get
{
return (childsection)base.baseget(key);
}
}
}
当然要使用此集合类我们必须在complex类中添加一个此集合类的属性,并要指定集合类的元素类型等属性,如下:
[configurationproperty("children", isdefaultcollection = false)]
[configurationcollection(typeof(childsection), collectiontype = configurationelementcollectiontype.addremoveclearmap, removeitemname = "remove")]
public children children
{
get
{
return (children)base["children"];
}
set
{
base["children"] = value;
}
}
我们会经常用到类似appsettings配置节的键值对的构造,这时候我们就不必再自己实现了,我们可以直接使用现有的system.configuration.namevalueconfigurationcollection类来定义一个自定义的键值对。可以在complex类中定义如下属性
[configurationproperty("nvs", isdefaultcollection = false)]
public system.configuration.namevalueconfigurationcollection nvs
{
get
{
return (namevalueconfigurationcollection)base["nvs"];
}
set
{
base["nvs"] = value;
}
}
然后在配置文件的complex节中添加键值对配置
<nvs>
<add name="abc" value="123"/>
<add name="abcd" value="12d3"/>
</nvs>
到这儿已经基本上可以满足所有的配置需求了。不过还有一点更大但是不复杂的概念,就是sectiongroup。我们可以自定义sectiongroup,然后在sectiongroup中配置多个section;分组对于大的应用程序是很有意义的。
如下配置,配置了一个包含simple和一个complex两个section的sectiongroup
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configsections>
<sectiongroup type="configexample.configuration.samplesectiongroup,configexample" name="samplegroup">
<section type="configexample.configuration.simplesection,configexample" allowdefinition="everywhere" name="simple" />
<section type="configexample.configuration.complexsection,configexample" allowdefinition="everywhere" name="complex"/>
</sectiongroup>
</configsections>
<samplegroup>
<simple maxvalue="20" minvalue="1">
</simple>
<complex height="190">
<child firstname="james" lastname="bond"/>
<children>
<add firstname="zhao" lastname="yukai"/>
<add firstname="lee" lastname="yukai"/>
<remove firstname="zhao"/>
</children>
<nvs>
<add name="abc" value="123"/>
<add name="abcd" value="12d3"/>
</nvs>
</complex>
</samplegroup>
</configuration>
为了方便的存取sectiongroup中的section我们可以实现一个继承自system.configuration.configurationsectiongroup类的自定义类。实现很简单,就是通过基类的sections[“sectionname”]索引器返回section。如下:
public class samplesectiongroup : system.configuration.configurationsectiongroup
{
public simplesection simple
{
get
{
return (simplesection)base.sections["simple"];
}
}
public complexsection complex
{
get
{
return (complexsection)base.sections["complex"];
}
}
}
需要注意的是sectiongroup不能使用configurationmanager.getsection(string)方法来获得,要获得sectiongroup必须通过configuration类的sectiongroups[string]索引器获得,如下示例代码:
samplesectiongroup sample = (samplesectiongroup)configurationmanager.openexeconfiguration(configurationuserlevel.none).sectiongroups["samplegroup"];
总结:
.net framework给我们提供了一套很方便的配置库,我们只需要继承对应的类简单的配置一下就可以方便的使用在web.config或者app.config中配置的自定义节点了。
自定义配置文件节源码
如果你已经对自定义配置了如指掌,请忽略这篇文章。
言归正传,我们先来看一个最简单的自定义配置
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configsections>
<section name="simple" type="configexample.configuration.simplesection,configexample"/>
</configsections>
<simple maxvalue="20" minvalue="1"></simple>
</configuration>
在配置文件中使用自定义配置,需要在configsections中添加一个section元素,并制定此section元素对应的类型和名字。然后再在configuration根节点下面添加此自定义配置,如上例中的simple节点。simple节点只有两个整形数的属性maxvalue和minvalue。
要在程序中使用自定义配置我们还需要实现存取这个配置块的类型,一般需要做如下三件事:
1. 定义类型从system.configuration.configurationsection继承
2. 定义配置类的属性,这些属性需要用configurationproperty特性修饰,并制定属性在配置节中的名称和其他一些限制信息
3. 通过基类的string索引器实现属性的get ,set
非常简单和自然,如下是上面配置类的实现:
复制代码 代码如下:
public class simplesection:system.configuration.configurationsection
{
[configurationproperty("maxvalue",isrequired=false,defaultvalue=int32.maxvalue)]
public int maxvalue
{
get
{
return (int)base["maxvalue"];
}
set
{
base["maxvalue"] = value;
}
}
[configurationproperty("minvalue",isrequired=false,defaultvalue=1)]
public int minvalue
{
get { return (int) base["minvalue"];}
set { base["minvalue"] = value; }
}
[configurationproperty("enabled",isrequired=false,defaultvalue=true)]
public bool enable
{
get
{
return (bool)base["enabled"];
}
set
{
base["enabled"] = value;
}
}
}
这样子一个简单的配置类就完成了,怎么在程序中使用这个配置呢?需要使用configurationmanager类(要引用system.configuration.dll这个dll只有在.net2.0之后的版本中才有)的getsection方法获得配置就可以了。如下代码:
复制代码 代码如下:
simplesection simple = configurationmanager.getsection("simple") as simplesection;
console.writeline("simple minvalue={0} maxvalue = {1}",simple.minvalue,simple.maxvalue);
这个配置类太过简陋了,可能有时候我们还需要更复杂的构造,比如在配置类中使用类表示一组数据,下面我们看一个稍微复杂一点的自定义配置
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configsections>
<section name="complex" type="configexample.configuration.complexsection,configexample"/>
</configsections>
<complex height="190">
<child firstname="james" lastname="bond"/>
</complex>
</configuration>
这个配置的名字是complex,他有一个属性height,他的节点内还有一个child元素这个元素有两个属性firstname和lastname;对于这个内嵌的节点该如何实现呢?首先我们需要定义一个类,要从configurationelement类继承,然后再用和simplesection类似的方法定义一些用configurationproperty特性修饰的属性就可以了,当然属性值的get,set也要使用基类的索引器。如下实现:
复制代码 代码如下:
public class complexsection : configurationsection
{
[configurationproperty("height", isrequired = true)]
public int height
{
get
{
return (int)base["height"];
}
set
{
base["height"] = value;
}
}
[configurationproperty("child", isdefaultcollection = false)]
public childsection child
{
get
{
return (childsection)base["child"];
}
set
{
base["child"] = value;
}
}
}
public class childsection : configurationelement
{
[configurationproperty("firstname", isrequired = true, iskey = true)]
public string firstname
{
get
{
return (string)base["firstname"];
}
set
{
base["firstname"] = value;
}
}
[configurationproperty("lastname", isrequired = true)]
public string lastname
{
get
{
return (string)base["lastname"];
}
set
{
base["lastname"] = value;
}
}
}
还有稍微再复杂一点的情况,我们可能要在配置中配置一组相同类型的节点,也就是一组节点的集合。如下面的配置:
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configsections>
<section name="complex" type="configexample.configuration.complexsection,configexample"/>
</configsections>
<complex height="190">
<child firstname="james" lastname="bond"/>
<children>
<add firstname="zhao" lastname="yukai"/>
<add firstname="lee" lastname="yukai"/>
<remove firstname="zhao"/>
</children>
</complex>
</configuration>
请看children节点,它就是一个集合类,在它里面定义了一组add元素,也可以有remove节点把已经添进去的配置去掉。
要使用自定义节点集合需要从configurationelementcollection类继承一个自定义类,然后要实现此类getelementkey(configurationelement element)和configurationelement createnewelement()两个方法;为了方便的访问子节点可以在这个类里面定义只读的索引器。请看下面的实现
复制代码 代码如下:
public class children : configurationelementcollection
{
protected override object getelementkey(configurationelement element)
{
return ((childsection)element).firstname;
}
protected override configurationelement createnewelement()
{
return new childsection();
}
public childsection this[int i]
{
get
{
return (childsection)base.baseget(i);
}
}
public childsection this[string key]
{
get
{
return (childsection)base.baseget(key);
}
}
}
当然要使用此集合类我们必须在complex类中添加一个此集合类的属性,并要指定集合类的元素类型等属性,如下:
复制代码 代码如下:
[configurationproperty("children", isdefaultcollection = false)]
[configurationcollection(typeof(childsection), collectiontype = configurationelementcollectiontype.addremoveclearmap, removeitemname = "remove")]
public children children
{
get
{
return (children)base["children"];
}
set
{
base["children"] = value;
}
}
我们会经常用到类似appsettings配置节的键值对的构造,这时候我们就不必再自己实现了,我们可以直接使用现有的system.configuration.namevalueconfigurationcollection类来定义一个自定义的键值对。可以在complex类中定义如下属性
复制代码 代码如下:
[configurationproperty("nvs", isdefaultcollection = false)]
public system.configuration.namevalueconfigurationcollection nvs
{
get
{
return (namevalueconfigurationcollection)base["nvs"];
}
set
{
base["nvs"] = value;
}
}
然后在配置文件的complex节中添加键值对配置
复制代码 代码如下:
<nvs>
<add name="abc" value="123"/>
<add name="abcd" value="12d3"/>
</nvs>
到这儿已经基本上可以满足所有的配置需求了。不过还有一点更大但是不复杂的概念,就是sectiongroup。我们可以自定义sectiongroup,然后在sectiongroup中配置多个section;分组对于大的应用程序是很有意义的。
如下配置,配置了一个包含simple和一个complex两个section的sectiongroup
复制代码 代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configsections>
<sectiongroup type="configexample.configuration.samplesectiongroup,configexample" name="samplegroup">
<section type="configexample.configuration.simplesection,configexample" allowdefinition="everywhere" name="simple" />
<section type="configexample.configuration.complexsection,configexample" allowdefinition="everywhere" name="complex"/>
</sectiongroup>
</configsections>
<samplegroup>
<simple maxvalue="20" minvalue="1">
</simple>
<complex height="190">
<child firstname="james" lastname="bond"/>
<children>
<add firstname="zhao" lastname="yukai"/>
<add firstname="lee" lastname="yukai"/>
<remove firstname="zhao"/>
</children>
<nvs>
<add name="abc" value="123"/>
<add name="abcd" value="12d3"/>
</nvs>
</complex>
</samplegroup>
</configuration>
为了方便的存取sectiongroup中的section我们可以实现一个继承自system.configuration.configurationsectiongroup类的自定义类。实现很简单,就是通过基类的sections[“sectionname”]索引器返回section。如下:
复制代码 代码如下:
public class samplesectiongroup : system.configuration.configurationsectiongroup
{
public simplesection simple
{
get
{
return (simplesection)base.sections["simple"];
}
}
public complexsection complex
{
get
{
return (complexsection)base.sections["complex"];
}
}
}
需要注意的是sectiongroup不能使用configurationmanager.getsection(string)方法来获得,要获得sectiongroup必须通过configuration类的sectiongroups[string]索引器获得,如下示例代码:
复制代码 代码如下:
samplesectiongroup sample = (samplesectiongroup)configurationmanager.openexeconfiguration(configurationuserlevel.none).sectiongroups["samplegroup"];
总结:
.net framework给我们提供了一套很方便的配置库,我们只需要继承对应的类简单的配置一下就可以方便的使用在web.config或者app.config中配置的自定义节点了。
自定义配置文件节源码