WCF後續之旅(5): 通過WCF Extension實現Localization
一、Message Service
1: namespace Artech.Messages.Contract
2: {
3: [ServiceContract]
4: public interface IMessage
5: {
6: [OperationContract]
7: string GetMessage();
8: }
9: }
1: namespace Artech.Messages.Service
2: {
3: public class MessageService:IMessage
4: {
5: public string GetMessage()
6: {
7: return Resources.HelloWorld;
8: }
9: }
10: }
1: namespace Artech.Messages.Hosting
2: {
3: public class Program
4: {
5: public static void Main()
6: {
7: using (ServiceHost host = new ServiceHost(typeof(MessageService)))
8: {
9: host.Opened += delegate
10: {
11: Console.WriteLine("Message service has been started up!");
12: };
13:
14: host.Open();
15:
16: Console.Read();
17: }
18: }
19: }
20: }
1: <configuration>
2: <system.serviceModel>
3: <services>
4: <service name="Artech.Messages.Service.MessageService">
5: <endpoint binding="basicHttpBinding" contract="Artech.Messages.Contract.IMessage" />
6: <host>
7: <baseAddresses>
8: <add baseAddress="https://127.0.0.1/messageservice" />
9: </baseAddresses>
10: </host>
11: </service>
12: </services>
13: </system.serviceModel>
14: </configuration>
1: <configuration>
2: <system.serviceModel>
3: <client>
4: <endpoint address="https://127.0.0.1/messageservice" binding="basicHttpBinding"
5: contract="Artech.Messages.Contract.IMessage" name="messageservice" />
6: </client>
7: </system.serviceModel>
8: </configuration>
1: namespace Artech.Messages.Client
2: {
3: class Program
4: {
5: private const string CultureInfoHeadLocalName = "__CultureInfo";
6: private const string CultyreInfoHeaderNamespace = "urn:artech.com";
7:
8: static void Main(string[] args)
9: {
10: using (ChannelFactory<IMessage> channelFactory = new ChannelFactory<IMessage>("messageservice"))
11: {
12: IMessage proxy = channelFactory.CreateChannel();
13: using (OperationContextScope contextScope = new OperationContextScope(proxy as IContextChannel))
14: {
15: MessageHeader<CultureInfo> header = new MessageHeader<CultureInfo>(Thread.CurrentThread.CurrentUICulture);
16: OperationContext.Current.OutgoingMessageHeaders.Add(header.GetUntypedHeader(CultureInfoHeadLocalName,CultyreInfoHeaderNamespace));
17: Console.WriteLine("The UI culture of current thread is {0}", Thread.CurrentThread.CurrentUICulture);
18: Console.WriteLine(proxy.GetMessage());
19: }
20:
21: Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN");
22: using (OperationContextScope contextScope = new OperationContextScope(proxy as IContextChannel))
23: {
24: MessageHeader<CultureInfo> header = new MessageHeader<CultureInfo>(Thread.CurrentThread.CurrentUICulture);
25: OperationContext.Current.OutgoingMessageHeaders.Add(header.GetUntypedHeader(CultureInfoHeadLocalName, CultyreInfoHeaderNamespace));
26: Console.WriteLine("The UI culture of current thread is {0}", Thread.CurrentThread.CurrentUICulture);
27: Console.WriteLine(proxy.GetMessage());
28: }
29: }
30:
31: Console.Read();
32: }
33: }
34: }
二、創建CallContextInitializer
1: public interface ICallContextInitializer
2: {
3: void AfterInvoke(object correlationState);
4: object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message);
5: }
1: namespace Artech.CallContextInitializers
2: {
3: public class CultureSettingCallContextInitializer:ICallContextInitializer
4: {
5: private const string CultureInfoHeadLocalName = "__CultureInfo";
6: private const string CultyreInfoHeaderNamespace = "urn:artech.com";
7: public void AfterInvoke(object correlationState)
8: {
9: CultureInfo[] currentCulture = correlationState as CultureInfo[];
10: Thread.CurrentThread.CurrentCulture = currentCulture[0];
11: Thread.CurrentThread.CurrentUICulture = currentCulture[1];
12: }
13:
14: public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
15: {
16: CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
17: CultureInfo currentUICulture = Thread.CurrentThread.CurrentUICulture;
18:
19: if (message.Headers.FindHeader(CultureInfoHeadLocalName, CultyreInfoHeaderNamespace) > -1)
20: {
21: CultureInfo cultureInfo = message.Headers.GetHeader<CultureInfo>(CultureInfoHeadLocalName, CultyreInfoHeaderNamespace);
22: Thread.CurrentThread.CurrentCulture = cultureInfo;
23: Thread.CurrentThread.CurrentUICulture = cultureInfo;
24: }
25:
26: return new CultureInfo[] { currentCulture, currentUICulture };
27: }
28: }
29: }
三、通過OperationBehavior應用CallContextInitializer
1: namespace Artech.CallContextInitializers
2: {
3: public class CultureSettingBehaviorAttribute:Attribute,IOperationBehavior
4: {
5: public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters){}
6: public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation){}
7: public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
8: {
9: dispatchOperation.CallContextInitializers.Add(new CultureSettingCallContextInitializer());
10: }
11: public void Validate(OperationDescription operationDescription){}
12: }
13: }
實際上隻有一句有意思的代碼,將CultureSettingCallContextInitializer對象設置到應用了OperationBehavior
1: dispatchOperation.CallContextInitializers.Add(new CultureSettingCallContextInitializer());
1: {
2: [ServiceContract]
3: public interface IMessage
4: {
5: [OperationContract]
6: [CultureSettingBehavior]
7: string GetMessage();
8: }
9: }
四、通過EndpointBehavior運用CallContextInitializer
1: namespace Artech.CallContextInitializers
2: {
3: public class CultureSettingBehavior: IEndpointBehavior
4: {
5: public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters){}
6:
7: public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime){}
8:
9: public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
10: {
11: foreach (var operation in endpointDispatcher.DispatchRuntime.Operations)
12: {
13: operation.CallContextInitializers.Add(new CultureSettingCallContextInitializer());
14: }
15: }
16:
17: public void Validate(ServiceEndpoint endpoint){}
18: }
19: }
1: namespace Artech.CallContextInitializers
2: {
3: public class CultureSettingBehaviorElement: BehaviorExtensionElement
4: {
5: public override Type BehaviorType
6: {
7: get
8: {
9: return typeof(CultureSettingBehavior);
10: }
11: }
12:
13: protected override object CreateBehavior()
14: {
15: return new CultureSettingBehavior();
16: }
17: }
18: }
1: <configuration>
2: <system.serviceModel>
3: <behaviors>
4: <endpointBehaviors>
5: <behavior name="cultureSettingBehavior">
6: <cultureSettingElement />
7: </behavior>
8: </endpointBehaviors>
9: </behaviors>
10: <extensions>
11: <behaviorExtensions>
12: <add name="cultureSettingElement" type="Artech.CallContextInitializers.CultureSettingBehaviorElement, Artech.CallContextInitializers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
13: </behaviorExtensions>
14: </extensions>
15: <services>
16: <service name="Artech.Messages.Service.MessageService">
17: <endpoint behaviorConfiguration="cultureSettingBehavior" binding="basicHttpBinding"
18: contract="Artech.Messages.Contract.IMessage" />
19: <host>
20: <baseAddresses>
21: <add baseAddress="https://127.0.0.1/messageservice" />
22: </baseAddresses>
23: </host>
24: </service>
25: </services>
26: </system.serviceModel>
27: </configuration>
WCF後續之旅:
WCF後續之旅(1): WCF是如何通過Binding進行通信的
WCF後續之旅(2): 如何對Channel Layer進行擴展——創建自定義Channel
WCF後續之旅(3): WCF Service Mode Layer 的中樞—Dispatcher
WCF後續之旅(4):WCF Extension Point 概覽
WCF後續之旅(5): 通過WCF Extension實現Localization
WCF後續之旅(6): 通過WCF Extension實現Context信息的傳遞
WCF後續之旅(7):通過WCF Extension實現和Enterprise Library Unity Container的集成
WCF後續之旅(8):通過WCF Extension 實現與MS Enterprise Library Policy Injection Application Block 的集成
WCF後續之旅(9):通過WCF的雙向通信實現Session管理[Part I]
WCF後續之旅(9): 通過WCF雙向通信實現Session管理[Part II]
WCF後續之旅(10): 通過WCF Extension實現以對象池的方式創建Service Instance
WCF後續之旅(11): 關於並發、回調的線程關聯性(Thread Affinity)
WCF後續之旅(12): 線程關聯性(Thread Affinity)對WCF並發訪問的影響
WCF後續之旅(13): 創建一個簡單的WCF SOAP Message攔截、轉發工具[上篇]
WCF後續之旅(13):創建一個簡單的SOAP Message攔截、轉發工具[下篇]
WCF後續之旅(14):TCP端口共享
WCF後續之旅(15): 邏輯地址和物理地址
WCF後續之旅(16): 消息是如何分發到Endpoint的--消息篩選(Message Filter)
WCF後續之旅(17):通過tcpTracer進行消息的路由
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-30 17:05:01
上一篇:
WCF後續之旅(4):WCF Extension Point 概覽
下一篇:
WCF後續之旅(6): 通過WCF Extension實現Context信息的傳遞
過去一年18個國家的大選活動遭遇黑客攻擊
Linq中調用本地方法
《TensorFlow技術解析與實戰》——第1章 人工智能概述 1.4什麼是TensorFlow
Java並發編程:線程池的使用
《機器人自動化:建模、仿真與控製》一一2.4習題
關於程序員的59條搞笑但卻真實無比的編程語錄
匹配指定id的HTMLDom元素的正則
Android自定義捕獲Application全局異常
[Android] Eclipse Warning: No grammar constraints (DTD or XML schema) detected for the document
開發人員和設計師應該安裝的10個Android應用