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





5.00/5 (11投票s)
一篇文章,演示如何使用 WCF 将文化信息从 Windows 客户端传递到 Windows 服务器。

目录
引言
在一个我正在进行的项目中,我们使用 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 日:初始发布