65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 Windows Communication Foundation 进行路由:第二部分 - 扩展 web.config

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2008 年 3 月 13 日

MPL

4分钟阅读

viewsIcon

24975

downloadIcon

82

实现路由规则的自定义配置。

引言

在 .NET 编程中,有时通用的 <appSettings> 配置节不足以满足您的需求。幸运的是,.NET Framework 提供了一个丰富的接口,可以创建自定义配置节供应用程序配置使用。

背景

这是关于 WCF 路由器(用于企业 WCTP 服务)的系列文章中的第二篇。各部分如下:

第一部分 - 概述
第二部分 - 扩展 web.config
第三部分 - 定义服务合同
第四部分 - 实现路由器
第五部分 - 异步服务实现
第六部分 - 同步服务实现
第七部分 - 高级服务

在本节中,我们将展示如何创建一个自定义配置节来存储路由器将发送信息的所有服务的设置。

设计

最终,我们希望在 XML 配置文件中有一个类似于以下内容的节:

<wctp>
  <receivers>
    <addReceiver name="Receiver1" intProperty="77" boolProperty="true" />
    <addReceiver name="Receiver2" intProperty="114" boolProperty="false" >
  </receivers>
</wctp>

这是通过使用三个派生自 System.Configuration 命名空间中基类的自定义类来实现的。它们是:

  1. 一个派生自 System.Configuration.ConfigurationSection 的类,代表 <wctp> 元素。
  2. 一个派生自 System.Configuration.ConfigurationElementCollection 的类,代表 <receivers> 元素以及 <addReceiver> 元素的能力。
  3. 一个派生自 System.Configuration.ConfigurationElement 的类,代表 <addReceiver> 元素中包含的属性信息。

让我们详细看看这些。

WctpConfig

WctpConfig 类是我们派生自 ConfigurationSection 的类,它代表了自定义配置的根 XML 元素。由于它只包含一个集合,所以代码非常简洁。

[ConfigurationProperty("receivers", IsDefaultCollection = false)]
[ConfigurationCollection(typeof(ReceiverCollection), AddItemName="addReceiver",
        ClearItemsName="clearReceivers", RemoveItemName="removeReceiver")]
public ReceiverCollection Receivers
{
  get
  {
    return (ReceiverCollection)(base["receivers"]);
  }
}

能够使用 <clearReceivers> 和 <removeReceiver> 元素允许我们进行机器到应用程序的设置,其中一些设置可以在 machine.config 文件或其他配置文件中定义。

ReceiverCollection

ReceiverCollection 类是派生自 ConfigurationElementCollection 的类。它包含通过整数索引或字符串键获取集合中元素的方法,以及添加、删除和清除子元素的方法。

这个类非常通用,只需稍作修改就可以轻松地用于其他项目。

ReceiverConfig

这是派生自 ConfigurationElement 的类。它包含了我们配置树的真正自定义代码。所以让我们看看它将为我们做什么。

在这个类中,我们将拥有决定 WCTP 消息应该路由到哪个接收器的必要信息。因此,我们希望它包含一些非常具体的信息:

  • 名称 - 这既是 ReceiverCollection 元素集合的键,也必须与配置的 WCF 端点匹配。
  • 优先级 - 当多个服务都匹配接收消息时,必须有一种方法来决定将消息发送到哪个服务。优先级是实现这一目标的好方法。
  • 收件人筛选器 - 这是针对消息发送到的 URI 的筛选器。例如,某个特定服务可能希望所有发送到 electric@contoso.com 的消息都由它处理。
  • 发件人筛选器 - 这是针对发送消息的无线电设备的 URI 的筛选器。例如,如果我们想插入一个用于一组以地址 602555121 开头的测试设备的测试服务,我们可以使用过滤器 "^602555121." 来限制某个服务只接收这些消息。
  • 格式处理 - WCTP 支持两种通用格式:二进制和文本。某些服务可能只支持这两种格式中的一种。因此,拥有指定此项的配置是一个好主意。
  • 独占处理 - 可以将消息发送到一个以上的服务。此设置允许配置指定是否应该将消息发送到其他优先级较低的服务。
  • 单向 - WCF 支持各种底层协议。某些服务可能不支持同步通信,而是依赖于特定的底层功能来保持消息,例如 MSMQ。此设置允许配置指定 WCF 服务合同是否具有 (IsOneWay=true) 操作。

实现这些相当直接。下面是一个 HandlesText 属性的示例。

/// 
/// Whether or not the service supports text messages.  True by default.
/// 
[ConfigurationProperty("text", IsRequired = false, DefaultValue = true)]
public bool HandlesText
{
  get
  {
    return (bool)this["text"];
  }
  set
  {
    this["text"] = value;
  }
}

使用集合

稍微跳到 WCTP HTTP 应用程序的实现,使用配置非常简单。在决定将特定消息路由到哪个 WCF 服务时,可以执行一个简单的 LINQ 查询,返回一个排序的潜在服务列表。

//Create a LINQ query to get the order of services to send the message to
WctpConfig config = (WctpConfig)(ConfigurationManager.GetSection("WCTP"));
IEnumerable<WctpConfig> receivers;
if (payload.GetType() == typeof(string))
{
  receivers = config.Receivers.OfType()
      .Where(s => s.HandlesText)
      .Where(s => Regex.Match(originator.senderID, s.SenderFilter).Success)
      .Where(s => Regex.Match(recipient.recipientID, s.RecipientFilter).Success)
      .OrderByDescending(s => s.Priority)
      .ThenByDescending(s => s.ExclusiveHandler)
      .ThenByDescending(s => s.OneWay);
}
else
{
  receivers = config.Receivers.OfType()
      .Where(s => s.HandlesBinary)
      .Where(s => Regex.Match(originator.senderID, s.SenderFilter).Success)
      .Where(s => Regex.Match(recipient.recipientID, s.RecipientFilter).Success)
      .OrderByDescending(s => s.Priority)
      .ThenByDescending(s => s.ExclusiveHandler)
      .ThenByDescending(s => s.OneWay);
}

这不是很好吗!

关注点

我越来越惊叹于 LINQ 中包含的功能。

历史

2008 年 3 月 13 日 - 原始文档

© . All rights reserved.