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


WCF的三個名稱/命名空間,你是否傻傻分不清楚?

在定義和寄宿WCF服務的時候會麵臨三個名稱/命名空間,它們分別是ServiceContractAttribute、ServiceBehaviorAttribute和Binding的Name和Namespace屬性,很對人對此不能很好地區分。

每個服務契約都有一個確定的名稱,當在一個接口或類上應用了ServiceContractAttribute特性,默認的名稱就是接口或類的名稱。我們可以通過Name屬性顯式地指定需要的名稱,這在某些場景中往往具有重要的作用。比如在客戶端有一個通過接口的形式定義的服務契約,現有的很多客戶端代碼均依賴於這個接口,如果這個時候服務方的名稱改變了,客戶端僅須更新這個Name屬性,從而避免修改接口的名稱而造成對現有代碼的影響。

   1: public sealed class ServiceContractAttribute : Attribute
   2: {   
   3:     //其他成員    
   4:     public string Name { get; set; }
   5:     public string Namespace { get; set; }
   6: }

至於服務契約的命名空間,其作用和我們托管語言(比如C#、VB.NET)的命名空間完全一樣,旨在解決命名衝突問題。很多WCF的編程人員都不太注重在定義服務契約的時候指定命名空間,這是一個不太好的習慣。我們鼓勵采用包含你所在的公司名稱或項目名稱作為命名空間。WCF默認采用的命名空間是https://tempuri.org/

作為服務的描述信息,服務契約作為WSDL的一部分以元數據的形式發布出來。WSDL通過<portType>元素定義相應的服務契約。ServiceContractAttribute的Name和Namespace屬性對應著用於描述服務契約的<portType>元素的名稱和命名空間。

   1: [ServiceContract(Name = "CaclService", Namespace = "https://www.artech.com/")]
   2: public interface ICalculator
   3: {
   4:     //省略成員
   5: }

如上麵的代碼所示,我們應用了ServiceContractAttribute特性將接口ICalculator接口定義成服務契約。ServiceContractAttribute的Name和Namespace分別被設置成CaclService和https://www.artech.com/"。服務契約將會對應著如下一段WSDL。

   1: <wsdl:definitions xmlns:wsdl="https://schemas.xmlsoap.org/wsdl/" 
   2:                   xmlns: tns = "https://www.artech.com/"...>
   3:    <wsdl:portType name="tns:CaclService">
   4:      ...
   5:   </wsdl:portType>
   6: </wsdl:definitions>

關於通過ServiceContractAttribute特性定義的服務契約的名稱和命名空間,很多人會和通過ServiceBehaviorAttribute定義的名稱和命名空間混淆。

   1: [AttributeUsage(AttributeTargets.Class)]
   2: public sealed class ServiceBehaviorAttribute : Attribute, IServiceBehavior
   3: {
   4:     //其他成員
   5:     public string Name { get; set; }
   6:     public string Namespace { get; set; }
   7: }

實際上服務行為特性ServiceBehaviorAttribute定義的是服務本身的名稱和命名控件。這兩個屬性將作為整個WSDL根節點< definitions >的name和targetNamespace屬性。如果沒有對其進行顯式設置,默認的命名空間為https://tempuri.org/。WCF將使用服務類型的名稱作為作為服務名稱。

   1: [ServiceBehavior(Name = "CaclService", 
   2:           Namespace ="https://www.artech.com")]
   3: public class CalculatorService : ICalculator
   4: {
   5:   //省略成員
   6: }

對於上麵定義的服務類型來說,由於我們通過ServiceBehaviorAttribute特性對名稱和命名空間進行了顯式設置。用於描述服務的WSDL將具有如下一個根節點。

   1: <wsdl:definitions  name="CaclService" 
   2:                    targetNamespace="https://www.artech.com"
   3:                    xmlns:wsdl="https://schemas.xmlsoap.org/wsdl/" ...>
   4: </wsdl:definitions>

既然已經將到了服務契約和服務的名稱和命名空間,我們順便來談談另一組命名和命名空間。其實作為終結點三要素之一的綁定也具有自己的名稱和命名空間。如下麵的代碼所示,作為綁定基類的抽象類Binding同樣具有一組Name和Namespace屬性。

   1: public abstract class Binding
   2: {
   3:     //省略成員
   4:     public string Name { get; set; }
   5:     public string Namespace { get; set; }
   6: }

Binding的名稱和命名空間通過服務終結點的bindingName和bindingNamespace屬性進行設置。由於這兩個屬性屬於服務描述範疇,所以客戶端終結點無此設置。由於綁定在WSDL中對應的節點為<binding>,所以綁定的Name和Namespace屬性值將作為對應的<binding>節點的名稱和命名空間。在默認的情況下,<binding>元素的命名空間的值依然是https://tempuri.org/。至於名稱,則通過綁定類型名稱和契約名稱合並而成。比如說契約名稱為ICalculator,並采用BasicHttpBinding,那麼對應的<binding>元數的名稱為BasicHttpBinding_ICalculator。

   1: <configuration>
   2:   <system.serviceModel>    
   3:     <services>
   4:       <service ...>
   5:         <endpoint bindingName="myBasicHttpBinding"
   6:                   bindingNamespace="https://www.artech.com" .../>
   7:       </service>
   8:     </services>
   9:   </system.serviceModel>
  10: </configuration>

比如說在服務寄宿時采用如上的配置將終結點的綁定名稱和命名空間進行了顯式設置,並且采用如上的服務契約(名稱被定義成CalcService)。該終結點綁定在WSDL中將對應於如下一個<binding>元素。

   1: <wsdl:definitions xmlns:wsdl="https://schemas.xmlsoap.org/wsdl/"
   2:                   xmlns:tns = "https://www.artech.com/">
   3:   <wsdl:binding name="tns: myBasicHttpBinding_CalcService" ...>    
   4:   </wsdl:binding>
   5: </wsdl:definitions>

要區分上述三個名稱/命名空間其實不然,隻要我們知道終結點三要素在WSDL具體對應什麼。


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

最後更新:2017-10-26 14:34:29

  上一篇:go  EndpointAddress——不隻是一個Uri[下篇]
  下一篇:go  通過定義UnityContainer擴展變”Explicit Interception”為”Automatic Interception”