自定义消息拦截器

MessageInterceptor 示例演示了通道扩展性模型的用法。 具体而言,它演示如何实现一个自定义绑定元素,该元素创建通道工厂和通道侦听器,以截获运行时堆栈中特定点的所有传入和传出消息。 此示例还包括一个客户端和服务器,用于演示这些自定义工厂的使用。

在此示例中,客户端和服务都是控制台程序(.exe)。 客户端和服务都使用包含自定义绑定元素及其关联的运行时对象的通用库(.dll)。

注释

本示例的设置过程和生成说明位于本主题末尾。

此示例介绍了使用通道框架和遵循 WCF 最佳做法在 Windows Communication Foundation(WCF)中创建自定义分层通道的建议过程。 创建自定义分层通道的步骤如下:

  1. 确定您的通道工厂和通道侦听器将要支持哪些通道形状。

  2. 创建支持您的通道形状的通道工厂和通道侦听器。

  3. 添加将自定义分层通道添加到通道堆栈的绑定元素。

  4. 添加绑定元素扩展部分,以向配置系统公开新的绑定元素。

通道形状

编写自定义分层通道的第一步是确定通道需要哪些形状。 对于我们的消息检查器,我们支持我们下面的层支持的任何形状(例如,如果我们下面的层可以生成 IOutputChannelIDuplexSessionChannel然后我们还会公开 IOutputChannelIDuplexSessionChannel)。

通道工厂和侦听器工厂

编写自定义分层通道的下一步是为客户端通道创建IChannelFactory的实现,为服务通道创建IChannelListener的实现。

这些类使用内部工厂和侦听器,除了 OnCreateChannelOnAcceptChannel 的调用外,所有其他调用都委托给内部工厂和侦听器。

class InterceptingChannelFactory<TChannel> : ChannelFactoryBase<TChannel>
{
    //...
}

class InterceptingChannelListener<TChannel> : ListenerFactoryBase<TChannel>
{
    //...
}

添加绑定元素

该示例定义自定义绑定元素: InterceptingBindingElement. InterceptingBindingElementChannelMessageInterceptor 作为输入,并使用这个 ChannelMessageInterceptor 来处理传递通过它的消息。 这是唯一必须公开的类。 工厂、侦听器和通道都可以是公共运行时接口的内部实现。

public class InterceptingBindingElement : BindingElement
{
}

添加配置支持

为了与绑定配置集成,库将配置节处理程序定义为绑定元素扩展节。 客户端和服务器配置文件必须向配置系统注册绑定元素扩展。 希望将其绑定元素公开给配置系统的实现程序可以从此类派生。

public abstract class InterceptingElement : BindingElementExtensionElement
{
    //...
}

添加策略

若要与策略系统集成,InterceptingBindingElement 实现 IPolicyExportExtension,用以指示我们参与策略生成。 若要支持在生成的客户端上导入策略,用户可以注册派生类 InterceptingBindingElementImporter 并重写 CreateMessageInterceptor() 以生成其启用策略的 ChannelMessageInterceptor 类。

示例:可丢弃的消息拦截器

此示例中包括了丢弃消息的 ChannelMessageInspector 的示例实现。

class DroppingServerElement : InterceptingElement
{
    protected override ChannelMessageInterceptor CreateMessageInterceptor()
    {
        return new DroppingServerInterceptor();
    }
}

可以从配置访问它,如下所示:

<configuration>
    ...
    <system.serviceModel>
        ...
        <extensions>
            <bindingElementExtensions>
                <add name="droppingInterceptor"
                   type=
          "Microsoft.ServiceModel.Samples.DroppingServerElement, library"/>
            </bindingElementExtensions>
        </extensions>
    </system.serviceModel>
</configuration>

客户端和服务器都使用此新创建的配置部分将自定义工厂插入到运行时通道堆栈(高于传输级别)的最低级别。

<customBinding>
  <binding name="sampleBinding">
    <droppingInterceptor/>
    <httpTransport/>
  </binding>
</customBinding>

客户端使用 MessageInterceptor 库在编号为偶数的消息中添加一个自定义头。 另一方面,服务使用 MessageInterceptor 库删除任何没有此特殊标头的消息。

运行服务和客户端后,您应该看到以下客户端输出。

Reporting the next 10 wind speed
100 kph
Server dropped a message.
90 kph
80 kph
Server dropped a message.
70 kph
60 kph
Server dropped a message.
50 kph
40 kph
Server dropped a message.
30 kph
20 kph
Server dropped a message.
10 kph
Press ENTER to shut down client

客户端向服务报告了 10 个不同的风速,但只用这个特殊的头标记了其中 5 个。

在服务上,应会看到以下输出:

Press ENTER to exit.
Dangerous wind detected! Reported speed (90) is greater than 64 kph.
Dangerous wind detected! Reported speed (70) is greater than 64 kph.
5 wind speed reports have been received.

设置、生成和运行示例

  1. 使用以下命令安装 ASP.NET 4.0。

    %windir%\Microsoft.NET\Framework\v4.0.XXXXX\aspnet_regiis.exe /i /enable
    
  2. 确保已为 Windows Communication Foundation 示例 执行One-Time 安装过程。

  3. 若要生成解决方案,请按照 生成 Windows Communication Foundation 示例中的说明进行作。

  4. 若要在单台计算机或跨计算机配置中运行示例,请按照 运行 Windows Communication Foundation 示例中的说明进行操作。

  5. 首先运行 Service.exe 然后运行 Client.exe 并监视两个控制台窗口的输出。