WCF後續之旅(8):通過WCF Extension 實現與MS Enterprise Library Policy Injection Application Block 的集成
在上一篇文章中,我們通過自定義InstanceProvider實現了WCF和微軟Enterprise Library Unity Application Block的集成, 今天我們已相同的方式實現WCF與Enterprise Library的另一個Application Block的集成:Policy Injection Application Block (PIAB)。
一、創建基於PolicyInjection的InstanceProvider
1: namespace Artech.WCFExtensions
2: {
3: public class PolicyInjectionInstanceProvider : IInstanceProvider
4: {
5: private Type _serviceContractType;
6: private string _policyInjectorName;
7:
8: public PolicyInjectionInstanceProvider(Type serviceContractType, string policyInjectorName)
9: {
10: this._serviceContractType = serviceContractType;
11: this._policyInjectorName = policyInjectorName;
12: }
13: public object GetInstance(InstanceContext instanceContext, Message message)
14: {
15: PolicyInjector policyInjector = null;
16: if (string.IsNullOrEmpty(this._policyInjectorName))
17: {
18: policyInjector = new PolicyInjectorFactory().Create();
19: }
20: else
21: {
22: policyInjector = new PolicyInjectorFactory().Create(this._policyInjectorName);
23: }
24:
25: Type serviceType = instanceContext.Host.Description.ServiceType;
26: object serviceInstance = Activator.CreateInstance(serviceType);
27: if (!this._serviceContractType.IsInterface && !serviceType.IsMarshalByRef && policyInjector is RemotingPolicyInjector)
28: {
29: return serviceInstance;
30: }
31:
32: return policyInjector.Wrap(serviceInstance, this._serviceContractType);
33: }
34:
35: public object GetInstance(InstanceContext instanceContext)
36: {
37: return this.GetInstance(instanceContext, null);
38: }
39:
40: public void ReleaseInstance(InstanceContext instanceContext, object instance)
41: {
42: IDisposable disposable = instance as IDisposable;
43: if (disposable != null)
44: {
45: disposable.Dispose();
46: }
47: }
48: }
49: }
1: PolicyInjector policyInjector = null;
2: if (string.IsNullOrEmpty(this._policyInjectorName))
3: {
4: policyInjector = new PolicyInjectorFactory().Create();
5: }
6: else
7: {
8: policyInjector = new PolicyInjectorFactory().Create(this._policyInjectorName);
9: }
1: Type serviceType = instanceContext.Host.Description.ServiceType;
2: object serviceInstance = Activator.CreateInstance(serviceType);
3: if (!this._serviceContractType.IsInterface && !serviceType.IsMarshalByRef && policyInjector is RemotingPolicyInjector)
4: {
5: return serviceInstance;
6: }
1: return policyInjector.Wrap(serviceInstance, this._serviceContractType);
二、為PolicyInjectionInstanceProvider創建Behavior
I、ContractBehavior:PolicyInjectionBehaviorAttribute
1: namespace Artech.WCFExtensions
2: {
3: public class PolicyInjectionBehaviorAttribute : Attribute, IContractBehavior
4: {
5: public string PolicyInjectorName{ get; set; }
6: public void AddBindingParameters(ContractDescription contractDescription, ServiceEndpoint endpoint, BindingParameterCollection bindingParameters){ }
7: public void ApplyClientBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, ClientRuntime clientRuntime){ }
8: public void ApplyDispatchBehavior(ContractDescription contractDescription, ServiceEndpoint endpoint, DispatchRuntime dispatchRuntime)
9: {
10: Type serviceContractType = contractDescription.ContractType;
11: dispatchRuntime.InstanceProvider = new PolicyInjectionInstanceProvider(serviceContractType, this.PolicyInjectorName);
12: }
13: public void Validate(ContractDescription contractDescription, ServiceEndpoint endpoint){
14: }
15: }
1: namespace Artech.WCFExtensions
2: {
3: public class PolicyInjectionBehavior : IEndpointBehavior
4: {
5: private string _policyInjectorName;
6: public PolicyInjectionBehavior(string policyInjectorName)
7: {
8: this._policyInjectorName = policyInjectorName;
9: }
10: public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters){ }
11: public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime){ }
12: public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
13: {
14: Type serviceContractType = endpoint.Contract.ContractType;
15: endpointDispatcher.DispatchRuntime.InstanceProvider = new PolicyInjectionInstanceProvider(serviceContractType, this._policyInjectorName);
16: }
17: public void Validate(ServiceEndpoint endpoint){ }
18: }
19: }
1: namespace Artech.WCFExtensions
2: {
3: public class PolicyInjectionBehaviorElement:BehaviorExtensionElement
4: {
5: [ConfigurationProperty("policyInjectorName",IsRequired = false, DefaultValue = "")]
6: public string PolicyInjectorName
7: {
8: get
9: {
10: return this["policyInjectorName"] as string;
11: }
12: set
13: {
14: this["policyInjectorName"] = value;
15: }
16: }
17:
18: public override Type BehaviorType
19: {
20: get { return typeof(PolicyInjectionBehavior); }
21: }
22:
23: protected override object CreateBehavior()
24: {
25: return new PolicyInjectionBehavior(this.PolicyInjectorName);
26: }
27: }
28: }
29:
三、應用我們的PolicyInjectionBehavior
I、Artech.TimeService.Contract
1: namespace Artech.TimeService.Contract
2: {
3: [ServiceContract]
4: [PolicyInjectionBehavior]
5: public interface ITime
6: {
7: [OperationContract]
8: DateTime GetCurrentTime();
9: }
10: }
II、Artech.TimeService.Service
1: namespace Artech.TimeService.Service
2: {
3: public class TimeService:ITime
4: {
5: [CachingCallHandler]
6: public DateTime GetCurrentTime()
7: {
8: return DateTime.Now;
9: }
10: }
11: }
III、Artech.TimeService.Hosting
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <system.serviceModel>
4: <services>
5: <service name="Artech.TimeService.Service.TimeService">
6: <endpoint behaviorConfiguration="" binding="basicHttpBinding"
7: contract="Artech.TimeService.Contract.ITime" />
8: <host>
9: <baseAddresses>
10: <add baseAddress="https://127.0.0.1/timeservice" />
11: </baseAddresses>
12: </host>
13: </service>
14: </services>
15: </system.serviceModel>
16: </configuration>
1: namespace Artech.TimeService.Hosting
2: {
3: class Program
4: {
5: static void Main(string[] args)
6: {
7: using (ServiceHost host = new ServiceHost(typeof(Artech.TimeService.Service.TimeService)))
8: {
9: host.Opened += delegate
10: {
11: Console.WriteLine("Time service has been started up!");
12: };
13: host.Open();
14:
15: Console.Read();
16: }
17: }
18: }
19: }
20:
IV、Artech.TimeService.Client
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <system.serviceModel>
4: <client>
5: <endpoint address="https://127.0.0.1/timeservice" binding="basicHttpBinding"
6: contract="Artech.TimeService.Contract.ITime" name="timeservice" />
7: </client>
8: </system.serviceModel>
9: </configuration>
1: namespace Artech.TimeService.Client
2: {
3: class Program
4: {
5: static void Main(string[] args)
6: {
7: using (ChannelFactory<ITime> channelFactory = new ChannelFactory<ITime>("timeservice"))
8: {
9: ITime proxy = channelFactory.CreateChannel();
10:
11: for (int i = 0; i < 10; i++)
12: {
13: Console.WriteLine(proxy.GetCurrentTime());
14: Thread.Sleep(1000);
15: }
16: }
17:
18: Console.Read();
19: }
20: }
21: }
22:
1: namespace Artech.TimeService.Contract
2: {
3: [ServiceContract]
4: //[PolicyInjectionBehavior]
5: public interface ITime
6: {
7: [OperationContract]
8: DateTime GetCurrentTime();
9: }
10: }
1: <?xml version="1.0" encoding="utf-8" ?>
2: <configuration>
3: <system.serviceModel>
4: <behaviors>
5: <endpointBehaviors>
6: <behavior name="PolicyInjectionBehavior">
7: <PolicyInjectionBehaviorExtension />
8: </behavior>
9: </endpointBehaviors>
10: </behaviors>
11: <extensions>
12: <behaviorExtensions>
13: <add name="PolicyInjectionBehaviorExtension" type="Artech.WCFExtensions.PolicyInjectionBehaviorElement, Artech.WCFExtensions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
14: </behaviorExtensions>
15: </extensions>
16: <services>
17: <service name="Artech.TimeService.Service.TimeService">
18: <endpoint behaviorConfiguration="PolicyInjectionBehavior" binding="basicHttpBinding"
19: contract="Artech.TimeService.Contract.ITime" />
20: <host>
21: <baseAddresses>
22: <add baseAddress="https://127.0.0.1/timeservice" />
23: </baseAddresses>
24: </host>
25: </service>
26: </services>
27: </system.serviceModel>
28: </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:04:47