終於我又看完了二期愛情保衛戰,太酸爽了,推薦連結:http://www.iqiyi.com/a_19rrgublqh.html?vfm=2008_aldbd,不多說,誰看誰入迷,下面言歸正傳,
看看這個很有意思的Behavior。
一: Behavior這個潑婦的厲害
在前面的文章中,我也清楚的說明了整個wcf通訊流,而Behavior這個潑婦可以在wcf通訊流中的任何地方插上一腳,蠻狠無比,利用的好,讓你上天堂,利用的不
好,讓你下地獄。。。下面讓你看看behavior到底有哪些可以注入的點???先畫個簡圖:
上面的圖,大概就是wcf的通訊簡圖,所有藍色字型都是Behavior注入的點,其中Client和Service端都可以注入,如果按照功能分的話,又可以分為“操作級別”和
”端點級別“,下面我來簡要的分解下。
二:端點級別Behavior
從圖中你也可以看到,訊息檢查器是放在Channel這個級別的,也就是說它可以監視Client和Server的入站請求,也就是說所有的請求都需要通過它轉發,如果
這樣的話,那我是不是可以在這個注入點上自由的修改,變更,攔截入站和出站請求,而且利用這個特性我還可以做很多的事情,比如日誌記錄,記錄統計等等,下
面我們來看看這個怎麼使用??? 只需要extends IEndpointBehavior 和 IDispatchMessageInspector,然後加入EndpointBehaviors即可。。。
1. IDispatchMessageInspector
1 public class MyDispatchMessageInspector : IDispatchMessageInspector 2 { 3 public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 4 { 5 Console.WriteLine(request.ToString()); 6 return request; 7 } 8 9 public void BeforeSendReply(ref Message reply, object correlationState) 10 { 11 Console.WriteLine(reply.ToString()); 12 } 13 }
2. IEndpointBehavior
1 public class MyEndpointBehavior : IEndpointBehavior 2 { 3 public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) 4 { 5 } 6 7 public void ApplyClientBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.ClientRuntime clientRuntime) 8 { 9 } 10 11 public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) 12 { 13 endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new MyDispatchMessageInspector()); 14 } 15 16 public void Validate(ServiceEndpoint endpoint) 17 { 18 } 19 }
3. 將MyEndpointBehavior加入到Host中
1 static void Main(string[] args) 2 { 3 ServiceHost host = new ServiceHost(typeof(HomeService), new Uri("http://127.0.0.1:1920")); 4 5 host.AddServiceEndpoint(typeof(IHomeService), new BasicHttpBinding(), "HomeServie"); 6 7 host.Description.Behaviors.Add(new ServiceMetadataBehavior() { HttpGetEnabled = true }); 8 9 host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); 10 11 host.Description.Endpoints[0].EndpointBehaviors.Add(new MyEndpointBehavior()); 12 13 host.Open(); 14 15 Console.WriteLine("服務已經開啟!!!"); 16 17 Console.Read(); 18 }
4. 最後我們看一下服務方法
1 public class HomeService : IHomeService 2 { 3 public string Update(string message) 4 { 5 Console.WriteLine("我在Action方法:" + message); 6 7 return "my reply!!!"; 8 } 9 }
下面看看效果。。。在效果圖中,你應該看到了。在我的Action中的方法前後各有一段“入站訊息”和“出站訊息”,是不是很爽???
三:操作級別Behavior
從文章開頭的簡圖中,你應該看到了,Operation級別的Behavior比較多,有“操作啟動器(IOperationInvoker)","引數檢查(IParameterInspector)“,
“訊息格式化器(IDispatchMessageFormatter)”等等。。。 為什麼說等等這個詞,很簡單啊,,,其實還有很多系統內建的,既然是Operation,那就必
然是針對方法的,還記得OperationContract是怎麼套在方法上的嗎??? 是特性,對吧,,,同樣的道理,OperationBehavior也是一樣,那怎麼用呢??
同樣也是很簡單的,繼承幾個介面即可。。。
<1> IParameterInspector 的玩法
其實沒什麼好說的,既然是屬於Operation下面的Behavior,那都是通過特性注入的,而這個IParameterInspector,可以做到類似Mvc的Model驗證,下面
我做個簡單的Action引數長度驗證(長度不超過8個字元)。
1. IParameterInspector
1 public class MyIParameterInspector : IParameterInspector 2 { 3 public int MaxLength { get; set; } 4 5 public MyIParameterInspector(int MaxLength) 6 { 7 this.MaxLength = MaxLength; 8 } 9 10 /// <summary> 11 /// 出站的操作 12 /// </summary> 13 /// <param name="operationName"></param> 14 /// <param name="outputs"></param> 15 /// <param name="returnValue"></param> 16 /// <param name="correlationState"></param> 17 public void AfterCall(string operationName, object[] outputs, object returnValue, object correlationState) 18 { 19 20 } 21 22 /// <summary> 23 /// 入站的引數 24 /// </summary> 25 /// <param name="operationName"></param> 26 /// <param name="inputs"></param> 27 /// <returns></returns> 28 public object BeforeCall(string operationName, object[] inputs) 29 { 30 foreach (var item in inputs) 31 { 32 if (Convert.ToString(item).Length > MaxLength) 33 { 34 throw new Exception("碼單,長度不能超過 " + MaxLength + " 個長度"); 35 } 36 } 37 38 return null; 39 } 40 }
2. IOperationBehavior
1 public class MyOperationBehavior : Attribute, IOperationBehavior 2 { 3 public int MaxLength { get; set; } 4 5 public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) 6 { 7 8 } 9 10 public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) 11 { 12 13 } 14 15 public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) 16 { 17 dispatchOperation.ParameterInspectors.Add(new MyIParameterInspector(MaxLength)); 18 } 19 20 public void Validate(OperationDescription operationDescription) 21 { 22 23 } 24 }
3. 在Action在加上MyOperationBehavior 這個 Attribute
1 public class HomeService : IHomeService 2 { 3 [MyOperationBehavior(MaxLength = 5)] 4 public string Update(string message) 5 { 6 Console.WriteLine("我在Action方法:" + message); 7 8 return "my reply!!!"; 9 } 10 }
4. 然後我在客戶端故意輸入大於5的字元,看看效果怎麼樣???
1 public class Program1 2 { 3 static void Main(string[] args) 4 { 5 HomeServiceClient client = new HomeServiceClient(); 6 7 client.Update("我故意輸入了很多的字元,哈哈。。。。。"); 8 9 Console.Read(); 10 } 11 }
5. 最後看看效果圖,可以看到,最終的入站訊息會丟擲一個異常。。。
<2> MessageFormatter,IOperationInvoker 的玩法
剩下的這兩個玩法都差不多,你只需要extends一下,然後加入到OperationBehavior即可,有了上面的思想,我想下面這些使用起來都不是問題吧。。。