玩转C科技.NET

从学会做人开始认识这个世界!http://volnet.github.io

导航

[WCF]契约查询ContractQueries

当我们拿到一个服务地址的时候该如何知道这个服务所提供的服务呢?如果是您自己开发的Service,这一点或许不需要兴师动众,但是如果是别人开发的服务,那么了解服务中的Endpoint将显得格外重要,本文将利用对[WCF]继承中所构建的服务代码进行分析。

打开其程序代码添加一个ConsoleApplication应用程序,新建程序,代码如下:

using System;
using System.ServiceModel.Description;

namespace ContractQueriesClient
{
    class Program
    {
        static void Main(string[] args)
        {
            // ?WSDL
            //string mexAddress = "http://localhost:8080/ScientificCalculatorService?WSDL";
            //MetadataExchangeClient MEXClient = new MetadataExchangeClient(new Uri(mexAddress), MetadataExchangeClientMode.HttpGet);
            // /MEX
            string mexAddress = "http://localhost:8080/ScientificCalculatorService/mex";

            MetadataExchangeClient MEXClient = new MetadataExchangeClient(new Uri(mexAddress), MetadataExchangeClientMode.MetadataExchange);
            MetadataSet metadata = MEXClient.GetMetadata();
            MetadataImporter importer = new WsdlImporter(metadata);

            ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();
            int endpointCounter = 0;
            foreach (ServiceEndpoint endpoint in endpoints)
            {
                Console.WriteLine("endpoints[{0}].Name = {1}", endpointCounter, endpoint.Name);
                Console.WriteLine("endpoints[{0}].Contract.Namespace = {1}", endpointCounter, endpoint.Contract.Namespace);
                Console.WriteLine("endpoints[{0}].Contract.Name = {1}", endpointCounter, endpoint.Contract.Name);
                endpointCounter++;
            }

            System.Collections.ObjectModel.Collection<ContractDescription> contracts = importer.ImportAllContracts();
            int contractCounter = 0;
            foreach (ContractDescription contract in contracts)
            {
                Console.WriteLine("contracts[{0}].Namespace = {1}", contractCounter, contract.Namespace);
                Console.WriteLine("contracts[{0}].Name = {1}", contractCounter, contract.Name);
                contractCounter++;
            }
        }
    }
}

这个项目我们不需要Add ServiceReference,因为我们只需分析那个“地址”所提供给我们的究竟是什么样的服务,而不是要去使用服务中的契约。

注意到?WSDL和MEX的MetadataExchangeClientMode是不一样的,一个是基于HttpGet,另一个则是基于MetadataExchange的。

MetadataExchangeClient类包含了很多方法:(MSDN)

Use the MetadataExchangeClient to download metadata. ……

However, you can use the MetadataExchangeClient directly to retrieve metadata as a MetadataSet that contains MetadataSection objects.

……

明确目标,我们要找的是服务中的Endpoint,一些有效的类为我们将Metadata转换为我们想要的Endpoint提供了很大的便利。

public abstract class MetadataImporter

Imports metadata into System.ServiceModel.Description.ServiceEndpoint objects. (将元数据导出为ServiceEndpoint)

很好,这正是我们所需要的,可是看到MetadataImporter前面的修饰符居然是个abstract,这让我们必须Use an implementation of the MetadataImporter abstract class to import service metadata.

通过MSDN,很快我们能找到:

The System.ServiceModel.Description.WsdlImporter type is the implementation of the MetadataImporter abstract class included with WCF. The System.ServiceModel.Description.WsdlImporter type imports WSDL metadata with attached policies that are bundled in a System.ServiceModel.Description.MetadataSet object.

恩,这正是我们要寻找的,它是一个具体实现,MetadataImporter importer = new WsdlImporter(metadata);
ImportAllContracts
When overridden in a derived class, returns a collection of contracts imported from the metadata.
ImportAllEndpoints
When overridden in a derived class, returns all endpoints in the metadata.
是它的两个有效方法,看来我们找到我们所要的东西了,于是用接下来的代码将import出来的Endpoint和Contract给显示了一通,结果很明显,和我们的料想(服务中我们真正所实现的)一致。

结果:

//endpoints[0].Name = WSHttpBinding_IScientificCalculator
//endpoints[0].Contract.Namespace = http://tempuri.org/
//endpoints[0].Contract.Name = IScientificCalculator
//contracts[0].Namespace = http://tempuri.org/
//contracts[0].Name = IScientificCalculator

posted on 2007-11-13 02:14  volnet(可以叫我大V)  阅读(382)  评论(0编辑  收藏  举报

使用Live Messenger联系我
关闭