Windows Communication Foundation入門(Part Two) )

來源:互聯網
上載者:User

本文為《WCF入門》第二部分。主要介紹了有關WCF的技術要素,例如Endpoint,Host,Address,Binding,Contract。介紹了WCF的編程模式,以“Hello World”為例,講解了如何定義一個WCF Service,如何完成用戶端與服務端的通訊,如何通過工具SvcUtil.exe和代碼編寫的方式實現用戶端。三、WCF的技術要素
作為基於SOA(Service Oriented Architecture)的一個架構產品,WCF最重要的就是能夠快捷的建立一個服務(Service)。如所示,一個WCF Service由下面三部分構成:
 

1、Service Class:一個標記了[ServiceContract]Attribute的類,在其中可能包含多個方法。除了標記了一些WCF特有的Attribute外,這個類與一般的類沒有什麼區別。
2、Host(宿主):可以是應用程式,進程如Windows Service等,它是WCF Service啟動並執行環境。
3、Endpoints:可以是一個,也可以是一組,它是WCF實現通訊的核心要素。

WCF Service由一個Endpoints集合組成,每個Endpoint就是用於通訊的入口,用戶端和服務端通過Endpoint交換資訊,如所示:
 

我們可以看到一個Endpoint由三部分組成:Address,Binding,Contract。便於記憶,我們往往將這三部分稱為是Endpoint的ABCs。

Address是Endpoint的網路地址,它標記了訊息發送的目的地。Binding描述的是如何發送訊息,例如訊息發送的傳輸協議(如TCP,HTTP),安全(如SSL,SOAP訊息安全)。Contract則描述的是訊息所包含的內容,以及訊息的組織和操作方式,例如是one-way,duplex和request/reply。所以Endpoint中的ABCs分別代表的含義就是:where,how,what。當WCF發送訊息時,通過address知道訊息發送的地址,通過binding知道怎樣來發送它,通過contract則知道發送的訊息是什麼。

在WCF中,類ServiceEndpoint代表了一個Endpoint,在類中包含的EndpointAddress,Binding,ContractDescription類型分別對應Endpoint的Address,Binding,Contract,如:
 

EndpointAddress類又包含URI,Identity和可選的headers集合組成,如:
 

Endpoint安全的唯一性識別通常是通過其URI的值,但為了避免一些特殊情況造成URI的重複,又引入了Identity附加到URI上,保證了Endpoint地址的唯一性。至於可選的AddressHeader則提供了一些附加的資訊,尤其是當多個Endpoint在使用同樣的URI地址資訊時,AddressHeader就非常必要了。

Binding類包含Name,Namespace和BindingElement集合,如:
 

Binding的Name以及Namespace是服務中繼資料(service’s metadata)的唯一標識。BindingElement描述的是WCF通訊時binding的方式。例如,SecurityBindingElement表示Endpoint使用SOAP訊息安全方式,而ReliableSessionBindingElement表示Endpoint利用可信賴訊息確保訊息的傳送。TcpTransportBindingElement則表示Endpoint利用TCP作為通訊的傳輸協議。每種BindingElement還有相應的屬性值,進一步詳細的描述WCF通訊的方式。

BindingElement的順序也非常重要。BindingElement集合通常會建立一個用於通訊的堆棧,其順序與BindingElement集合中元素順序一致。集合中最後一個binding element對應於通訊堆棧的底部,而集合中的第一個binding element則對應於堆棧的頂端。入訊息流程的方向是從底部經過堆棧向上,而出訊息流程的方向則從頂端向下。因此,BindingElement集合中的binding element順序直接影響了通訊堆棧處理訊息的順序。幸運的是,WCF已經提供了一系列預定義的Binding,能夠滿足大多數情況,而不需要我們自訂Binding,殫精竭慮地考慮binding element的順序。

下表是WCF中預定義的Binding:

Class Name

Element Name
Transport
Encoding
WS-* Protocols
BasicHttpBinding
basicHttpBinding
HTTP
XML 1.0
WS-I Basic Profile 1.1
WSHttpBinding
wsHttpBinding
HTTP
XML 1.0
Message security, reliable sessions, and transactions
WSDualHttpBinding
wsDualHttpBinding
HTTP
XML 1.0
Message security, reliable sessions, and transactions
NetTcpBinding
netTcpBinding
TCP
Binary
Transport security, reliable sessions, and transactions
NetNamedPipeBinding
netNamedPipeBinding
Named Pipes
Binary
Transport security, reliable sessions, and transactions
NetMsmqBinding
netMsmqBinding
MSMQ
Binary
Transport security and queue transactions

Contract是一組操作(Operations)的集合,該操作定義了Endpoint通訊的內容,每個Operation都是一個簡單的訊息交換(message exchange),例如one-way或者request/reply訊息交換。

類ContractDescription用於描述WCF的Contracts以及它們的操作operations。在ContractDescription類中,每個Contract的operation都有相對應的OperationDescription,用於描述operation的類型,例如是one-way,還是request/reply。在OperationDescription中還包含了MessageDecription集合用於描述message。

在WCF編程模型中,ContractDescription通常是在定義Contract的介面或類中建立。對於這個介面或類類型,標記以ServiceContractAttribute,而其Operation方法則標記以OperationContractAttribute。當然我們也可以不利用CLR的attribute,而採用手工建立。

與Binding一樣,每個Contract也包含有Name和Namespace,用於在Service的中繼資料中作為唯一性識別。此外,Contract中還包含了ContractBehavior的集合,ContractBehavior類型可以用於修改或擴充contract的行為。類ContractDescription的組成如所示:
 

正如在ContractDescription中包含的IContractBehavior一樣,WCF專門提供了行為Behavior,它可以對用戶端和服務端的一些功能進行修改或者擴充。例如ServiceMetadataBehavior用於控制Service是否發布中繼資料。相似的,security behavior用於控制安全與授權,transaction behavior則控制事務。

除了前面提到的ContractBehavior,還包括ServiceBehavior和ChannelBehaivor。ServiceBehavior實現了IServiceBehavior介面,ChannelBehaivor則實現了IChannleBehavior介面。

由於WCF需要管理的是服務端與用戶端的通訊。對於服務端,WCF提供了類ServiceDescription用於描述一個WCF Service,;而針對用戶端,WCF管理的是發送訊息時需要使用到的通道Channel,類ChannelDescription描述了這樣的用戶端通道。

ServiceDescription類的組成如所示:
 

我們可以利用代碼的方式建立ServiceDescription對象,也可以利用WCF的Attribute,或者使用工具SvcUtil.exe。雖然可以顯式的建立它,但通常情況下,它會作為運行中的Service一部分而被隱藏於後(我在後面會提到)。

ChannelDescription類的組成與ServiceDescription大致相同,但它僅僅包含了一個ServiceEndpoint,用於表示用戶端通過通道通訊的目標Endpoint。當然,施加到ChannelDescription的Behavior也相應的為IChannelBehavior介面類型,:
 

定義一個WCF Service非常簡單,以Hello World為例,定義的Service可能如下:
using System.ServiceModel
[ServiceContract]
public class HelloWorld
{
    [OperationContract]
 public void Hello()
 {
  Console.WriteLine(“Hello World!”);
 }
}

System.ServiceModel是微軟為WCF提供的一個新的類庫,以用於面向服務的程式設計。在開發WCF應用程式時,需要先添加對System.ServiceModel的引用。WCF中的大部分類和介面也都是在命名空間System.ServiceModel下。

我們為HelloWorld類標記了[ServiceContract],這就使得該類成為了一個WCF Service,而其中的方法Hello()則因為標記了[OperationContract],而成為該Service的一個Operation。

不過WCF推薦的做法是將介面定義為一個Service,這使得WCF Service具有更好的靈活性,畢竟對於一個介面而言,可以在同時有多個類實現該介面,這也就意味著可以有多個Service Contract的實現。那麼上面的例子就可以修改為:
[ServiceContract]
public interface IHello
{
 [OperationContract]
 void Hello();
}

而類HelloWorld則實現該IHello介面:
public class HelloWorld:IHello
{
 public void Hello()
 {
  Console.WriteLine(“Hello World!”);
 }
}

注意在實現了IHello介面的類HelloWorld中,不再需要在類和方法中標註ServiceContractAttribute和OperationContractAttribute了。

前面我已經提過,一個WCF Service必須有host作為它啟動並執行環境。這個host可以是ASP.Net,可以是Windows Service,也可以是一個普通的應用程式,例如控制台程式。下面就是一個Host的實現:
using System.ServiceModel
public class HostApp
{
 static void Main(string[] args)
 {
  ServiceHost host = new ServiceHost(typeof(HelloWorld), new Uri(“http://localhost:8080/HelloService”));
  host.AddServiceEndpoint(typeof(IHello), new BasicHttpBinding(),”Svc”);
  host.Open();
  Console.WriteLine(“Start Your Service.”);
  Console.ReadKey();
  host.Close();
 }
}

在這個HostApp中,我們為HelloWorld建立了一個ServiceHost對象。通過它就可以建立WCF運行時(Runtime),WCF Runtime是一組負責接收和發送訊息的對象。ServiceHost可以建立SerivceDescription對象,利用SerivceDescription,SercieHost為每一個ServiceEndpoint建立一個EndpointListener。ServiceHost的組成如:
 

EndpointListener接聽程式包含了listening address,message filtering和dispatch,它們對應ServiceEndpoint中的EndpointAddress,Contract和Binding。在EndpointListener中,還包含了一個Channel Stack,專門負責發送和接收訊息。

注意在建立ServiceHost時,傳遞的type型別參數,不能是interface。因此,我在這裡傳入的是typeof(HelloWorld)。ServiceHost類的AddServiceEndpoint()方法實現了為Host添加Endpoint的功能,其參數正好是Endpoint的三部分:Address,Bingding和Contract。(此時的IHello即為ServiceContract,其方法Hello為OperationContract)。

ServiceHost的Open()方法用於建立和開啟Service運行時,而在程式結束後我又調用了Close()方法,來關閉這個運行時。實際上以本例而言,該方法可以不調用,因為在應用程式結束後,系統會自動關閉該host。但作為一種良好的編程習慣,WCF仍然要求顯式調用Close()方法,因為Service運行時其本質是利用Channel來完成訊息的傳遞,當開啟一個Service運行時的時候,系統會佔用一個Channel,調用完後,我們就需要釋放對該通道的佔用。當然我們也可以用using語句來管理ServiceHost資源的釋放。

定義好了一個WCF Service,並將其運行在Host上後,如何?它與用戶端的通訊呢?典型的情況下,服務端與用戶端均採用了Web Service Description Language(WSDL),用戶端可以通過工具SvcUtil.exe產生對應於該WCF Service的Proxy代碼,以完成之間的訊息傳遞,:
 

SvcUtil.exe是由WinFx Runtime Component SDK所提供的,如果安裝SDK正確,可以在其中找到該應用工具。產生用戶端Proxy代碼的方法很簡單,首先需要運行服務端Service。然後再命令列模式下運行下面的命令:
SvcUtil http://localhost:8080/HelloService

這樣會在目前的目錄下產生兩個檔案output.cs和output.config。前者最主要的就是包含了一個實現了IHello介面的Proxy對象,這個代理對象名為HelloProxy,代碼產生的結果如下:
[System.CodeDom.Compiler.GeneratedCodeAttribute(”System.ServiceModel”, “3.0.0.0″)]
public partial class HelloProxy : System.ServiceModel.ClientBase, IHello
{   
    public HelloProxy()
    {
    }   
    public HelloProxy(string endpointConfigurationName) :
            base(endpointConfigurationName)
    {
    }   
    public HelloProxy(string endpointConfigurationName, string remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
    {
    }   
    public HelloProxy(string endpointConfigurationName, System.ServiceModel.EndpointAddress remoteAddress) :
            base(endpointConfigurationName, remoteAddress)
    {
    }   
    public HelloProxy(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :
            base(binding, remoteAddress)
    {
    }   
    public void Hello()
    {
        base.InnerProxy.Hello();
    }
}
(註:本程式在WinFx 2006 February CTP版本下運行通過)

至於後者,則是WCF Service的配置資訊,主要包含的是Endpoint中Address,Binding以及Contract的配置(在後續文章我會詳細介紹)。

現在用戶端就可以直接使用HelloProxy對象,來完成與服務端的通訊了:
public class ClientApp
{
 static void Main(string[] args)
    {
        using (HelloProxy proxy = new HelloProxy())
  {
         proxy.Hello();
        }
Console.ReadKey();
    }
}

除了可以使用SvcUtil工具產生用戶端代碼,同樣我們也可以利用代碼的方式來完成用戶端。用戶端在發送訊息給服務端時,其通訊的基礎是Service的Endpoint,WCF提供了System.ServiceModel.Description.ServiceEndpoint類,通過建立它來實現兩端的通訊。在前面,我還提到“對於用戶端而言,WCF管理的是發送訊息時需要使用到的通道Channel”,為此,WCF提供了ChannelFactory(其命名空間為System.ServiceModel.Channel),專門用於建立用戶端運行時(runtime)。ChannelFactory與ServiceHost相對應,它可以建立ChannelDescription對象。與服務端ServiceHost不同的是,用戶端並不需要接聽程式,因為用戶端往往是建立串連的“發起方”,並不需要偵聽進來的串連。因此用戶端的Channel Stack會由ChannelDescription建立。

ChannelFactory和ServiceHost都具有Channel Stack,而服務端與用戶端的通訊又是通過channel來完成,這就意味著,利用ChannelFactory,用戶端可以發送訊息到服務端。而用戶端本身並不存在Service對象,因此該Service的Proxy,是可以通過Channel來得到的。所以用戶端的代碼可以修改如下:
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channel

public class ClientApp
{
 static void Main(string[] args)
    {
        ServiceEndpoint httpEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IHello)), new BasicHttpBinding(), new EndpointAddress(“http://localhost:8080/HelloService/Svc”));

  using (ChannelFactory factory = new ChannelFactory(httpEndPoint))
  {
   //建立IHello服務的代理對象;
   IHello service = factory.CreateChannel();
   service.Hello();
  }
  Console.ReadKey();
    }
}
(註:本程式在WinFx 2006 February CTP版本下運行通過)

對於上面的代碼,我們有兩點需要注意:
1、採用這種方式,前提條件是用戶端能夠訪問IHello介面。這也印證了之前我所敘述的最好使用interface來定義Service的好處。此外,為了保證部署的方便,有關Service的interface最好單獨編譯為一個程式集,便於更好的部署到用戶端。
2、用戶端必須知道服務端binding的方式以及address。

對於服務端而言,我們也可以直接在瀏覽器中開啟該Service,在地址欄中輸入http://localhost:8080/HelloService,如:
 

點選連結:http://localhost:8080/HelloService?wsdl,我們可以直接看到HelloService的WSDL。注意到在這裡我並沒有使用IIS,實際上WCF內建了對httpsys的整合,允許任何應用程式自動成為HTTP listener。

參考:
1、David Chappell,Introducing Windows Communication Foundation
2、Aaron Skonnard,Learn The ABCs Of Programming Windows Communication Foundation
3、Microsoft Corporation,Windows Communication Foundation Architecture Overview

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.