一.目的
一般应用都有自己的配置文件,如何将配置文件映射到.NET中的对象是有现实意义的事情,在Java中有一个digester开源项目实现了这个功能,下面我一步一步来说明.NET中如何更简单的实现他
二.实现
1.定义xsd架构文件,我们定义几个简单的架构
源文件如下:
<?xml version="1.0" encoding="utf-8"?
<xs:schema id="MyConfig" targetNamespace="ConfigTest" elementFormDefault="qualified" xmlns="ConfigTest" xmlns:mstns="ConfigTest" xmlns:xs="http://www.w3.org/2001/XMLSchema"
<xs:complexType name="select" mixed="true"
<xs:sequence/
<xs:attribute name="id" type="xs:string" /
<xs:attribute name="resultMap" type="xs:string" /
<xs:attribute name="cacheModel" type="xs:string" use="optional" /
<xs:attribute name='sql' type='xs:string' /
</xs:complexType
<xs:complexType name="update" mixed="true"
<xs:sequence /
<xs:attribute name="id" type="xs:string" /
<xs:attribute name="parameterMap" type="xs:string" /
<xs:attribute name='sql' type='xs:string' /
</xs:complexType
<xs:element name="statements"
<xs:complexType
<xs:sequence
<xs:element name="select" type="select" minOccurs="0" maxOccurs="unbounded" /
<xs:element name="update" type="update" minOccurs="0" maxOccurs="unbounded" /
</xs:sequence
</xs:complexType
</xs:element
</xs:schema
2.使用xsd.exe生成对应于架构的配置类
xsd.exe MyConfig.xsd /c
//------------------------------------------------------------------------------
// <autogenerated
//
This code was generated by a tool.
//
Runtime Version:2.0.40607.16
//
//
Changes to this file may cause incorrect behavior and will be lost if
//
the code is regenerated.
// </autogenerated
//------------------------------------------------------------------------------
using System.Xml.Serialization;
//
// This source code was auto-generated by xsd, Version=2.0.40607.16.
//
namespace ConfigDll
{
/// <remarks/
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "ConfigTest")]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "ConfigTest", IsNullable = false)]
public class statements
{
private select[] selectField;
private update[] updateField;
/// <remarks/
[System.Xml.Serialization.XmlElementAttribute("select")]
public select[] select
{
get
{
return this.selectField;
}
set
{
this.selectField = value;
}
}
/// <remarks/
[System.Xml.Serialization.XmlElementAttribute("update")]
public update[] update
{
get
{
return this.updateField;
}
set
{
this.updateField = value;
}
}
}
/// <remarks/
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "ConfigTest")]
public class select
{
private string idField;
private string resultMapField;
private string cacheModelField;
private string sqlField;
/// <remarks/
[System.Xml.Serialization.XmlAttributeAttribute()]
public string id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
/// <remarks/
[System.Xml.Serialization.XmlAttributeAttribute()]
public string resultMap
{
get
{
return this.resultMapField;
}
set
{
this.resultMapField = value;
}
}
/// <remarks/
[System.Xml.Serialization.XmlAttributeAttribute()]
public string cacheModel
{
get
{
return this.cacheModelField;
}
set
{
this.cacheModelField = value;
}
}
/// <remarks/
[System.Xml.Serialization.XmlTextAttribute()]
public string sql
{
get
{
return this.sqlField;
}
set
{
this.sqlField = value;
}
}
}
/// <remarks/
[System.SerializableAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "ConfigTest")]
public class update
{
private string idField;
private string parameterMapField;
private string sqlField;
/// <remarks/
[System.Xml.Serialization.XmlAttributeAttribute()]
public string id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
/// <remarks/
[System.Xml.Serialization.XmlAttributeAttribute()]
public string parameterMap
{
get
{
return this.parameterMapField;
}
set
{
this.parameterMapField = value;
}
}
/// <remarks/
[System.Xml.Serialization.XmlTextAttribute()]
public string sql
{
get
{
return this.sqlField;
}
set
{
this.sqlField = value;
}
}
}
}
3.实现IConfigurationSectionHandler接口
#region Using directives
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Reflection;
using System.Configuration;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Schema;
#endregion
namespace ConfigDll
{
public class MyConfigHandler : IConfigurationSectionHandler
{
private Type _configType = typeof(statements);
private string _schemaResourceName = "ConfigDll.MyConfig.xsd";
private string _schemaNamespace = "ConfigTest";
public MyConfigHandler()
{
}
public object Create(object parent, object configContext, System.Xml.XmlNode section)
{
XmlSerializer ser = new XmlSerializer(_configType);
// Create the XmlSchemaSet class.
XmlSchemaSet sc = new XmlSchemaSet();
// Add the schema to the collection.
Stream schemaStream = Assembly.GetAssembly(_configType).GetManifestResourceStream(_schemaResourceName);
sc.Add(_schemaNamespace, new XmlTextReader(schemaStream));
// Set the validation settings.
XmlReaderSettings settings = new XmlReaderSettings();
settings.XsdValidate = true;
settings.Schemas = sc;
settings.ValidationEventHandler += this.ValidationEventHandle;
XmlReader reader = XmlReader.Create(XmlReader.Create(new StringReader(section.OuterXml)), settings);
return ser.Deserialize(reader);
}
public void ValidationEventHandle(object sender, ValidationEventArgs args)
{
Console.WriteLine("\t验证错误:" + args.Message);
}
}
}
当然你可以建一个通用的校验类,这里只为演示
如果使用VS2003,校验需要使用XmlValidatingReader类,考虑到它在.NET2.0中已经过时所以使用新的方式
4.在App.Config中使用自定义配置节点
<?xml version="1.0" encoding="utf-8" ?
<configuration
<configSections
<section name="statements" type="ConfigDll.MyConfigHandler,ConfigDll" /
</configSections
<stat