十五天精通WCF——第九天 高階玩法之自定義Behavior

一線碼農發表於2015-07-05

 

  終於我又看完了二期愛情保衛戰,太酸爽了,推薦連結: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即可,有了上面的思想,我想下面這些使用起來都不是問題吧。。。

 

相關文章