找回密码
 立即注册
首页 业界区 业界 WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供 ...

WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

港髁 2025-5-29 15:04:51
我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置;通过ChannelFactory创建服务代理对象。在这篇文章中,我们采用一种独特的方式进行服务的调用。从本质上讲,我们只要能够创建于服务端相匹配的终结点,就能够实现正常的服务调用。在WCF客户端元数据架构体系中,利用MetadataExchangeClient可以获取服务的元数据,而利用MetadataImporter将获取的元数据导入成ServiceEndpoint对象。在本例中,我们将利用这两个组件定义了一个独特的服务调用的简单的例子,相信可以帮助读者进一步加深对WCF元数据框架体系的理解。 (Source从这里下载)
我们依然采用我们熟悉的计算服务的例子,下面是该服务相应的服务契约、服务类型的定义和寄宿该服务采用的配置。
  1.    1: <?xml version="1.0" encoding="utf-8" ?>using System.ServiceModel;
复制代码
  1.    2: <configuration>namespace Artech.ServiceInvocationViaMetadata.Contracts
复制代码
  1.    3: {
复制代码
  1.    4:     [ServiceContract(Namespace = "http://www.artech.com/")]
复制代码
  1.    5:     public interface ICalculator
复制代码
  1.    6:     {
复制代码
  1.    7:         [OperationContract]
复制代码
  1.    8:         double Add(double x, double y);
复制代码
  1.    9:     }
复制代码
  1.   10: }
复制代码
服务类型:
  1.    1: <?xml version="1.0" encoding="utf-8" ?>using System.ServiceModel;
复制代码
  1.    2: <configuration>using Artech.ServiceInvocationViaMetadata.Contracts;
复制代码
  1.    3: 
复制代码
  1.    4: namespace Artech.ServiceInvocationViaMetadata.Services
复制代码
  1.    5: {
复制代码
  1.    6:     public class CalculatorService : ICalculator
复制代码
  1.    7:     {
复制代码
  1.    8:         public double Add(double x, double y)
复制代码
  1.    9:         {
复制代码
  1.   10:         </behaviors>    return x + y;
复制代码
  1.   11:         <services>}
复制代码
  1.   12:     }
复制代码
  1.   13: }
复制代码
配置:
  1.    1: <?xml version="1.0" encoding="utf-8" ?>
复制代码
  1.    2: <configuration>
复制代码
  1.    3:     <system.serviceModel>
复制代码
  1.    4:         <behaviors>
复制代码
  1.    5:             <serviceBehaviors>
复制代码
  1.    6:                 <behavior name="mexBehavior">
复制代码
  1.    7:                     <serviceMetadata />
复制代码
  1.    8:                 </behavior>
复制代码
  1.    9:             </serviceBehaviors>
复制代码
  1.   10:         </behaviors>
复制代码
  1.   11:         <services>
复制代码
  1.   12:             <service behaviorConfiguration="mexBehavior" name="Artech.ServiceInvocationViaMetadata.Services.CalculatorService">
复制代码
  1.   13:                 <endpoint address="http://127.0.0.1:3721/calculatorservice" binding="ws2007HttpBinding" contract="Artech.ServiceInvocationViaMetadata.Contracts.ICalculator" />
复制代码
  1.   14:                 <endpoint address="http://127.0.0.1:3721/calculatorservice/mex" binding="mexHttpBinding" contract="IMetadataExchange" />
复制代码
  1.   15:             </service>
复制代码
  1.   16:         </services>
复制代码
  1.   17:     </system.serviceModel>
复制代码
  1.   18: </configuration>
复制代码
从上面的配置我们可以看到,服务的元数据通过WS-MEX模式发布出来,发布的地址和采用的MEX绑定分别为:http://127.0.0.1:3721/calculatorservice/mex和mexHttpBinding。
接下来,我们就可以通过下面的方式对该服务进行调用了。我们先创建MetadataExchangeClient对象并利用它获取包含元数据的MetadataSet对象,并利用该对象创建WsdlImporter对象。接下来,我们将基于ICalculator接口的服务契约添加到该WsdlImporter的已知契约列表中,调用ImportAllEndpoints方法得到导入的ServiceEndpoint列表。最后根据导出的ServiceEndpoint对象创建ChannelFactory对象,并创建服务代理进行服务调用。
  1.    1: <?xml version="1.0" encoding="utf-8" ?>sing System;
复制代码
  1.    2: <configuration>using System.ServiceModel;
复制代码
  1.    3: using System.ServiceModel.Description;
复制代码
  1.    4: using System.Xml;
复制代码
  1.    5: using Artech.ServiceInvocationViaMetadata.Contracts;
复制代码
  1.    6: namespace Artech.ServiceInvocationViaMetadata.Client
复制代码
  1.    7: {
复制代码
  1.    8:     class Program
复制代码
  1.    9:     {
复制代码
  1.   10:         </behaviors>static void Main(string[] args)
复制代码
  1.   11:         <services>{
复制代码
  1.   12:             <service behaviorConfiguration="mexBehavior" name="Artech.ServiceInvocationViaMetadata.Services.CalculatorService">MetadataExchangeClient metadataExchangeClient = new MetadataExchangeClient(MetadataExchangeBindings.CreateMexHttpBinding());
复制代码
  1.   13:             MetadataSet metadata = metadataExchangeClient.GetMetadata(new EndpointAddress("http://127.0.0.1:3721/calculatorservice/mex"));
复制代码
  1.   14:             WsdlImporter wsdlImporter = new WsdlImporter(metadata);
复制代码
  1.   15:             </service>//添加已知契约类型
复制代码
  1.   16:         </services>    ContractDescription contract = ContractDescription.GetContract(typeof(ICalculator));
复制代码
  1.   17:     </system.serviceModel>        wsdlImporter.KnownContracts.Add(new XmlQualifiedName(contract.Name, contract.Namespace), contract);
复制代码
  1.   18: </configuration>            ServiceEndpointCollection endpoints = wsdlImporter.ImportAllEndpoints();
复制代码
  1.   19:             using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(endpoints[0]))
复制代码
  1.   20:             {
复制代码
  1.   21:                 ICalculator calculator = channelFactory.CreateChannel();
复制代码
  1.   22:                 using (calculator as IDisposable)
复制代码
  1.   23:                 {
复制代码
  1.   24:                     try
复制代码
  1.   25:                     {
复制代码
  1.   26:                         Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2));
复制代码
  1.   27:                     }
复制代码
  1.   28:                     catch(TimeoutException)
复制代码
  1.   29:                     {
复制代码
  1.   30:                         (calculator as ICommunicationObject).Abort();
复制代码
  1.   31:                         throw;
复制代码
  1.   32:                     }
复制代码
  1.   33:                     catch(CommunicationException)
复制代码
  1.   34:                     {
复制代码
  1.   35:                         (calculator as ICommunicationObject).Abort();
复制代码
  1.   36:                         throw;
复制代码
  1.   37:                     }
复制代码
  1.   38:                 }
复制代码
  1.   39:             }
复制代码
  1.   40:             Console.Read();
复制代码
  1.   41:         }
复制代码
  1.   42:     }
复制代码
  1.   43: }
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册