WCF獲取元數據

所謂獲取WCF的服務元數據(Metadata),歸根結點,實際上就是獲取服務的終結點(Endpoint)的信息,這是服務公開在外的數據信息,包括Address、Binding與Contract,也就是所謂的ABCs。Juval Löwy在《Programming WCF Services》一書中,用生動形象的棒棒糖表示了終結點的構成:
 figure-1.5.gifide

WCF服務可能包含多個終結點,每一個終結點至關因而通訊的入口,客戶端和服務端經過終結點交換信息,以下圖所示:
 wcf07.gif函數

於是,若是可以獲取終結點的詳細信息,有助於咱們更好地剖析服務的定義、內容與執行方式。學習

服務有兩種方案能夠發佈本身的元數據。一種是基於HTTP-GET協議提供元數據;另外一種則爲元數據交換方式,它每每使用一個專門的終結點,稱之爲元數據交換終結點。元數據交換終結點與其它終結點類似,仍然包含了地址、綁定與契約,可是使用的服務契約爲WCF提供的接口IMetadataExchange。對象

實際上,這兩種發佈元數據的方式表明了它使用了兩種不一樣的標準協議,前者爲HTTP/GET請求,後者爲WS-MetadataExchange(MEX)。在WCF,以MetadataExchangeClientMode枚舉類型表示這兩種元數據交換模式:
public enum MetadataExchangeClientMode
{
   MetadataExchange,
   HttpGet
}blog

WCF爲終結點定義了一個專門的ServiceEndpoint類,被定義在System.ServiceModel.Description命名空間中。ServiceEndpoint類包含了EndpointAddress,Binding,ContractDescription三個類型的屬性,分別對應Endpoint的Address,Binding,Contract,以下圖:
 wcf08.gif繼承

要獲取服務的終結點,能夠經過抽象類MetadataImporter獲取,類的定義以下:
    public abstract class MetadataImporter
    {
        public abstract Collection<ContractDescription> ImportAllContracts();
        public abstract ServiceEndpointCollection ImportAllEndpoints();
        //其它方法略;
}接口

在類中,最重要的一個方法是ImportAllEndpoints(),它可以獲取服務的全部終結點,並返回一個ServiceEndpointCollection類型的對象。該類型爲一個終結點集合,能夠經過調用ServiceEndpointCollection的Find()方法或FindAll()方法,找到符合條件的一個或多個終結點。它的定義以下:
    public class ServiceEndpointCollection : Collection<ServiceEndpoint>
    {
        public ServiceEndpoint Find(Type contractType);
        public ServiceEndpoint Find(Uri address);ip

        public Collection<ServiceEndpoint> FindAll(Type contractType);
        //其它成員略
    }string

咱們能夠經過契約類型,或者服務契約的地址,查找符合條件的終結點。it

MetadataImporter類只是一個抽象類,若是要獲取WSDL元數據,還會須要使用繼承它的子類型WsdlImporter:
    public class WsdlImporter : MetadataImporter
    {
        public WsdlImporter(MetadataSet metadata);

        public Collection<Binding> ImportAllBindings();
        public override Collection<ContractDescription> ImportAllContracts();
        public override ServiceEndpointCollection ImportAllEndpoints();
        public ServiceEndpointCollection ImportEndpoints(Binding wsdlBinding);
        //其它成員略;
    }

若是要使用WsdlImporter,須要爲其構造函數傳遞一個MetadataSet類型的對象。而MetadataSet類型的對象則能夠經過MetadataExchangeClient類的GetMetadata()方法得到。MetadataExchangeClient類的定義以下所示:
    public class MetadataExchangeClient
    {
        public MetadataExchangeClient();
        public MetadataExchangeClient(Binding mexBinding);
        public MetadataExchangeClient(EndpointAddress address);
        public MetadataExchangeClient(string endpointConfigurationName);
        public MetadataExchangeClient(Uri address, MetadataExchangeClientMode mode);

        public MetadataSet GetMetadata();
        public MetadataSet GetMetadata(EndpointAddress address);
        public MetadataSet GetMetadata(Uri address, MetadataExchangeClientMode mode);

        //其它方法略;
}

假定服務公開的元數據地址爲http://localhost:8001/IMyService?wsdl,則獲取服務元數據的方法以下:
string mexAddress = 「http://localhost:8001/IMyService?wsdl」;
BasicHttpBinding binding = new BasicHttpBinding();
MetadataExchangeClient mexClient = new MetadataExchangeClient(binding);
MetadataSet metadata = mexClient.GetMetadata(new Uri(mexAddress), MetadataExchangeClientMode.HttpGet);
MetadataImporter importer = new WsdlImporter(metadata);
ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();

注意,若是是HttpGet模式,則元數據地址的後綴必須爲?wsdl。因爲咱們在調用MetadataExchangeClient的GetMetadata()方法時,傳遞的MetadataExchangeClientMode枚舉參數值爲HttpGet,所以獲取的爲基於HTTP-GET的元數據。

若是服務使用的協議爲HTTP或者HTTPS,則可能使用元數據交換終結點,也可能爲Http-Get模式。此時,咱們能夠先獲取元數據交換終結點,若是沒有找到,再獲取基於HTTP-GET的終結點:
string mexAddress = 「http://localhost:8001/IMyService?wsdl」;
BasicHttpBinding binding = new BasicHttpBinding();
MetadataExchangeClient mexClient = new MetadataExchangeClient(binding);
MetadataSet metadata = mexClient.GetMetadata(new EndpointAddress(mexAddress));
MetadataImporter importer = new WsdlImporter(metadata);
ServiceEndpointCollection endpoints = importer.ImportAllEndpoints();

if (endpoints == null)
{
string httpGetAddress = mexAddress;
if (!mexAddress.EndsWith(「?wsdl」) )
{
    httpGetAddress += 「?wsdl」;
}
BasicHttpBinding binding = new BasicHttpBinding();
MetadataExchangeClient mexClient = new MetadataExchangeClient(binding);
MetadataSet metadata = mexClient.GetMetadata(new Uri(mexAddress), MetadataExchangeClientMode.HttpGet);
MetadataImporter importer = new WsdlImporter(metadata);
endpoints = importer.ImportAllEndpoints();
}

在得到ServiceEndpointCollection集合對象後,就能夠針對每一個ServiceEndpoint獲取終結點的Address、Binding、Contract的信息,以下所示:
foreach (ServiceEndpoint endpoint in endpoints)
{
Console.WriteLine(「Endpoint Name is {0}」, endpoint.Name);
Console.WriteLine(「Address is {0}」, endpoint.Address.Uri.AbsoluteUri);
Console.WriteLine(「Binding is {0}」, endpoint.Binding.GetType().ToString());
Console.WriteLine(「Address is {0}」, endpoint.Contract.Name);
Console.WriteLine();
}

經過以上介紹的類,採用類似的途徑,還能夠獲取更多元數據信息,例如服務契約、回調契約、基地址、地址、綁定等信息。

 

以上內容是轉發學習記錄過程。勿噴

相關文章
相關標籤/搜索