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

使用自定义行为通过 WCF 实现自动文化流

starIconstarIconstarIconstarIconstarIcon

5.00/5 (11投票s)

Nov 30, 2007

CPOL

3分钟阅读

viewsIcon

66626

downloadIcon

1200

一篇文章,演示如何使用 WCF 将文化信息从 Windows 客户端传递到 Windows 服务器。

Screenshot - CultureServer.png

目录

引言

在一个我正在进行的项目中,我们使用 WCF 从 Internet 客户端与 Windows 服务进行通信。 WCF 自动允许 Windows 身份从客户端流向服务器。 这很好,但对于客户端的文化信息来说并非如此。 如果文化信息也能从客户端流向服务器,从例如资源文件中读取本地化数据对应用程序来说可能完全透明。 本示例演示了如何通过实现自定义 WCF MessageInspector 来实现这样的解决方案。

背景

给定的扩展仅应在您控制线路两端(客户端和服务器)时使用。 如果您只创建服务器并关心互操作性,最好使用更标准的方法,如 Pablo Cibraro 撰写的 WCF 中的全球化模式(WS-I18N 实现) 中描述的方法。

WCF 有几个扩展点; 在本例中,使用自定义 MessageInspector。 自定义 MessageInspector 可用于在消息通过 WCF 客户端或服务器对象时检查或修改它们。 要检查或修改消息在客户端传递时的消息,您应该实现 IClientMessageInspector 接口。 要检查或修改消息在服务器传递时的消息,您应该实现 IDispatchMessageInspector 接口。 本例中的自定义 MessageInspector 实现了这两个接口。

自定义 MessageInspector 在客户端向请求添加自定义消息头,该消息头包含运行客户端的线程的文化信息。 在服务器端,自定义 MessageInspector 从自定义消息头中检索文化信息,并设置运行线程的文化信息。

要使用自定义消息检查器,还需要创建实现 IEndpointBehavior 的自定义行为。 然后将此行为添加到 WCF 终结点的行为集合中。

Using the Code

该解决方案分为四个项目:服务器、客户端、扩展和服务接口。 有趣的部分是扩展项目。 在本例中,客户端设置当前线程的文化信息,并调用服务器上的一个简单的“hello world”方法。 服务器使用运行线程的文化信息响应 Console.Writeline

MessageInspector(消息检查器)

这是自定义消息检查器,客户端的 BeforeSendRequest 添加消息头,而服务器的 AfterReceiveRequest 提取自定义头并设置当前执行线程的文化信息。

public class CultureMessageInspector : 
    IClientMessageInspector, IDispatchMessageInspector
{
  private const string HeaderKey = "culture";

  public object BeforeSendRequest
        (ref System.ServiceModel.Channels.Message request,
        System.ServiceModel.IClientChannel channel)
  {
    request.Headers.Add(MessageHeader.CreateHeader
        (HeaderKey, string.Empty, Thread.CurrentThread.CurrentUICulture.Name));
    return null;
  }

  public object AfterReceiveRequest
        (ref System.ServiceModel.Channels.Message request, 
        System.ServiceModel.IClientChannel channel,
        System.ServiceModel.InstanceContext instanceContext)
  {
    int headerIndex = request.Headers.FindHeader(HeaderKey, string.Empty);
    if (headerIndex != -1)
    {
      Thread.CurrentThread.CurrentUICulture = 
            new CultureInfo(request.Headers.GetHeader<string />(headerIndex));
    }
    return null;
  }
  ...

自定义行为

自定义行为是这样创建的

public class CultureBehaviour : IEndpointBehavior
{
  public void ApplyClientBehavior(ServiceEndpoint endpoint, 
        System.ServiceModel.Dispatcher.ClientRuntime clientRuntime)
  {
    clientRuntime.MessageInspectors.Add(new CultureMessageInspector());
  }

  public void ApplyDispatchBehavior(ServiceEndpoint endpoint, 
        System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher)
  {
    endpointDispatcher.DispatchRuntime.MessageInspectors.Add
                    (new CultureMessageInspector());
  }
  ...

创建服务主机

创建 ServiceHost 时,将自定义行为添加到 ServiceEndPoint 的行为集合中。 这也可以在配置文件中配置。

Server server = new Server();
ServiceHost host = 
    new ServiceHost(server, new Uri("net.tcp://:8080"));
NetTcpBinding binding = new NetTcpBinding();
ServiceEndpoint endPoint = 
    host.AddServiceEndpoint(typeof(IHelloWorld), binding, "Server");
endPoint.Behaviors.Add(new CultureBehaviour());

创建客户端通道

创建客户端通道时,自定义行为也添加到 ServiceEndPoint 的行为集合中。 这也可以在配置文件中配置。

ServiceEndpoint tcpEndPoint = new ServiceEndpoint(
    ContractDescription.GetContract(typeof(IHelloWorld)), 
        new NetTcpBinding(), new EndpointAddress
        ("net.tcp://:8080/server"));
ChannelFactory factory = new ChannelFactory(tcpEndPoint);
factory.Endpoint.Behaviors.Add(new CultureBehaviour());
return factory.CreateChannel();

关注点

我不确定运行 AfterReceiveRequest 的线程是否与运行实际服务器代码的线程相同。 在这种情况下确实如此。 如果您需要来自消息头的数据在 WCF 管道的另一部分中使用,您应该将数据添加到请求的属性集合中。

在我找到正确的扩展点后,实际的实现很简单。 存在许多扩展点,找到正确的扩展点是困难的部分。

历史

  • v1.0 2007 年 11 月 27 日:初始发布
© . All rights reserved.