为扩展程序提供可自定义的配置文件的方法(二)

本文详细介绍了在WCF中使用自定义配置文件的方法,包括extensions和custom两个自定义节点的应用,以及如何通过SenderCollection类处理配置信息,实现不同类型的集合配置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    上次介绍了还有另外两种自定义配置文件的办法,这次介绍WCF所采用的方法。

    请看配置文件:

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
<? xml version = " 1.0 " encoding = " utf-8 " ?>
< configuration >
< configSections >
< section name = " extensions " type = " CustomConfiguration.Configuration.ExtensionConfigurationSection, CustomConfiguration " />
< section name = " custom " type = " CustomConfiguration.Configuration.CustomConfigurationSection, CustomConfiguration " />
</ configSections >
< extensions >
< add name = " smtp " type = " CustomConfiguration.Configuration.SmtpSenderElement, CustomConfiguration " />
< add name = " sms " type = " CustomConfiguration.Configuration.SenderElement, CustomConfiguration " />
</ extensions >
< custom >
< senders >
< smtp name = " smtp " semaphore = " 10 " type = " CustomConfiguration.SmtpSender, CustomConfiguration " >
< authorization userName = " abcd " userPassword = " 1234 " />
</ smtp >
< sms name = " sms " semaphore = " 1 " type = " CustomConfiguration.SmsSender, CustomConfiguration " />
</ senders >
</ custom >
</ configuration >

 

     

    有两个自定义节点,extensions和custom,其中extensions定义了扩展类所使用自定义配置文件的处理类,当程序在custom节点中遇到自定义的节点,就会使用这里定义好的类来处理,这是扩展类自定义配置文件的核心。custom是我们的示例节点,定义了一个senders属性,这是一个集合,里面定义了实现了ISender接口的类,以及实例化这个类所需要的相关配置。

 
  
internal interface ISender
{
bool Send( string message);
void ApplyConfiguration(Configuration.SenderElement element);
}

 

     其中Send方法是业务方法,ApplyConfiguration方法不是必须的,因为实现类可以自行通过访问配置文件来获得自己的配置信息,这里为了简单起见,定义了一个方法,方便使用。

      核心类SenderCollection,这是一个配置类,处理custom节点的senders子节点,继承自ConfigurationElement。虽然是一个Collection,但是并没有继承自ConfigurationElementCollection,原因是ConfigurationElementCollection只能创建同一类型的元素集合,要想创建不同类型的集合,只能自己实现,这也就是本文的重点。代码如下:

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
internal sealed class SenderCollection : ConfigurationElement, IEnumerable < SenderElement >
{
private readonly List < SenderElement > m_Elements = new List < SenderElement > ();

protected override void DeserializeElement(System.Xml.XmlReader reader, bool serializeCollectionKey)
{
if (reader.HasAttributes && ( 0 < reader.AttributeCount))
{
while (reader.MoveToNextAttribute())
{
if ( this .Properties.Contains(reader.Name))
{
base [reader.Name] = this .Properties[reader.Name].Converter.ConvertFromString(reader.Value);
}
else
{
this .OnDeserializeUnrecognizedAttribute(reader.Name, reader.Value);
}
}
}
if (XmlNodeType.Element != reader.NodeType)
{
reader.MoveToElement();
}
XmlReader reader2
= reader.ReadSubtree();
if (reader2.Read())
{
while (reader2.Read())
{
if (XmlNodeType.Element == reader2.NodeType)
{
SenderElement element
= this .CreateNewSection(reader2.Name);
m_Elements.Add(element);
element.DeserializeInternal(reader2,
false );
}
}
}
}

private SenderElement CreateNewSection( string name)
{
var typeName
= ExtensionConfigurationSection.Current.Extensions.GetElement(name);
var local
= (SenderElement)Activator.CreateInstance(Type.GetType(typeName));
local.InternalInitializeDefault();
return local;
}
#region IEnumerable<SenderElement> 成员

public IEnumerator < SenderElement > GetEnumerator()
{
return m_Elements.GetEnumerator();
}

#endregion

#region IEnumerable 成员

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}

#endregion

 

      重载了DeserializeElement方法,自己来实现了xml文件的解析,中间的关键步骤在于每读到一个子节点,就调用CreateNewSection方法来创建一个自定义的配置元素对象,创建的方法是通过查找extensions节点来获得自定义配置元素的类型,然后创建这个类型的实例化对象,并且调用初始化方法。创建完毕以后调用DeserializeInternal方法来让配置文件自己处理自己的节点,这是重用System.Configuration框架的关键,通过这个可以采用声明式的方法来定义自己的配置类,而无需像上篇文章一样手动处理XmlRead。由于CreateNewSection需要通过查找来获得对应配置类,这也是为什么要把extensions独立出来一个配置节点,否则由于当前配置节点还没有处理完毕,这个时候访问当前配置节点,会造成循环调用,结果就是堆栈溢出。

      Main方法如下,循环遍历senders,构造对象,调用send方法测试:

ContractedBlock.gif ExpandedBlockStart.gif 代码
 
   
static void Main( string [] args)
{
foreach (SenderElement e in Configuration.CustomConfigurationSection.Current.Senders)
{
ISender sender
= (ISender)Activator.CreateInstance(Type.GetType(e.Type));
sender.ApplyConfiguration(e);
sender.Send(
" Hello world! " );
}
Console.ReadLine();
}

 

 

      示例项目文件下载

转载于:https://www.cnblogs.com/wenhx/archive/2010/08/11/CustomConfiguration-2.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值