閱讀252 返回首頁    go 阿裏雲 go 技術社區[雲棲]


WCF技術剖析之二十九:換種不同的方式調用WCF服務[提供源代碼下載]

我們有兩種典型的WCF調用方式:通過SvcUtil.exe(或者添加Web引用)導入發布的服務元數據生成服務代理相關的代碼和配置;通過ChannelFactory<TChannel>創建服務代理對象。在這篇文章中,我們采用一種獨特的方式進行服務的調用。從本質上講,我們隻要能夠創建於服務端相匹配的終結點,就能夠實現正常的服務調用。在WCF客戶端元數據架構體係中,利用MetadataExchangeClient可以獲取服務的元數據,而利用MetadataImporter將獲取的元數據導入成ServiceEndpoint對象。在本例中,我們將利用這兩個組件定義了一個獨特的服務調用的簡單的例子,相信可以幫助讀者進一步加深對WCF元數據框架體係的理解。 (Source從這裏下載)

我們依然采用我們熟悉的計算服務的例子,下麵是該服務相應的服務契約、服務類型的定義和寄宿該服務采用的配置。

   1: using System.ServiceModel;
   2: namespace Artech.ServiceInvocationViaMetadata.Contracts
   3: {
   4:     [ServiceContract(Namespace = "https://www.artech.com/")]
   5:     public interface ICalculator
   6:     {
   7:         [OperationContract]
   8:         double Add(double x, double y);
   9:     }
  10: }

服務類型:

   1: using System.ServiceModel;
   2: using Artech.ServiceInvocationViaMetadata.Contracts;
   3:  
   4: namespace Artech.ServiceInvocationViaMetadata.Services
   5: {
   6:     public class CalculatorService : ICalculator
   7:     {
   8:         public double Add(double x, double y)
   9:         {
  10:             return x + y;
  11:         }
  12:     }
  13: }

配置:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:     <system.serviceModel>
   4:         <behaviors>
   5:             <serviceBehaviors>
   6:                 <behavior name="mexBehavior">
   7:                     <serviceMetadata />
   8:                 </behavior>
   9:             </serviceBehaviors>
  10:         </behaviors>
  11:         <services>
  12:             <service behaviorConfiguration="mexBehavior" name="Artech.ServiceInvocationViaMetadata.Services.CalculatorService">
  13:                 <endpoint address="https://127.0.0.1:3721/calculatorservice" binding="ws2007HttpBinding" contract="Artech.ServiceInvocationViaMetadata.Contracts.ICalculator" />
  14:                 <endpoint address="https://127.0.0.1:3721/calculatorservice/mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  15:             </service>
  16:         </services>
  17:     </system.serviceModel>
  18: </configuration>

從上麵的配置我們可以看到,服務的元數據通過WS-MEX模式發布出來,發布的地址和采用的MEX綁定分別為:https://127.0.0.1:3721/calculatorservice/mex和mexHttpBinding。

接下來,我們就可以通過下麵的方式對該服務進行調用了。我們先創建MetadataExchangeClient對象並利用它獲取包含元數據的MetadataSet對象,並利用該對象創建WsdlImporter對象。接下來,我們將基於ICalculator接口的服務契約添加到該WsdlImporter的已知契約列表中,調用ImportAllEndpoints方法得到導入的ServiceEndpoint列表。最後根據導出的ServiceEndpoint對象創建ChannelFactory<ICalculator>對象,並創建服務代理進行服務調用。

   1: sing System;
   2: using System.ServiceModel;
   3: using System.ServiceModel.Description;
   4: using System.Xml;
   5: using Artech.ServiceInvocationViaMetadata.Contracts;
   6: namespace Artech.ServiceInvocationViaMetadata.Client
   7: {
   8:     class Program
   9:     {
  10:         static void Main(string[] args)
  11:         {
  12:             MetadataExchangeClient metadataExchangeClient = new MetadataExchangeClient(MetadataExchangeBindings.CreateMexHttpBinding());
  13:             MetadataSet metadata = metadataExchangeClient.GetMetadata(new EndpointAddress("https://127.0.0.1:3721/calculatorservice/mex"));
  14:             WsdlImporter wsdlImporter = new WsdlImporter(metadata);
  15:             //添加已知契約類型
  16:             ContractDescription contract = ContractDescription.GetContract(typeof(ICalculator));
  17:             wsdlImporter.KnownContracts.Add(new XmlQualifiedName(contract.Name, contract.Namespace), contract);
  18:             ServiceEndpointCollection endpoints = wsdlImporter.ImportAllEndpoints();
  19:             using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(endpoints[0]))
  20:             {
  21:                 ICalculator calculator = channelFactory.CreateChannel();
  22:                 using (calculator as IDisposable)
  23:                 {
  24:                     try
  25:                     {
  26:                         Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2));
  27:                     }
  28:                     catch(TimeoutException)
  29:                     {
  30:                         (calculator as ICommunicationObject).Abort();
  31:                         throw;
  32:                     }
  33:                     catch(CommunicationException)
  34:                     {
  35:                         (calculator as ICommunicationObject).Abort();
  36:                         throw;
  37:                     }
  38:                 }
  39:             }
  40:             Console.Read();
  41:         }
  42:     }
  43: }

作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-27 16:34:10

  上一篇:go  WCF技術剖析之二十八:自己動手獲取元數據[附源代碼下載]
  下一篇:go  WCF技術剖析之三十:一個很有用的WCF調用編程技巧[上篇]