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


WCF技術剖析之二十五: 元數據(Metadata)架構體係全景展現[元數據描述篇]

[WS標準篇]中我花了很大的篇幅介紹了WS-MEX以及與它相關的WS規範:WS-Policy、WS-Transfer和WSDL,因為WCF元數據結構體係完全是基於WS-MEX等相關的規範之上。熟悉這些基本的WS規範,對於我們全麵、深刻的理解WCF整個元數據架構體係具有十分重要的意義。不僅僅是針對元數據,對於後續章節陸續要介紹的內容,比如事務、可靠會話、安全等,我強烈建議讀者在正式進行相關部分的學習之前,先對相關的WS規範作一個大致的了解。

通過對WS-MEX的介紹,我們知道:不論是采用WS-Transfer Get操作還是Get Metadata操作,獲取到的元數據被封裝到回複消息主體部分的<Metadata>結點中,而<Metadata>是一組<MetadataSection>元素的集合。在托管的世界裏,<MetadataSection>元素和<MetadataSection>元素集合有相應的類型來表示,那就是我們接下來要著重介紹的MetadataSectionMetadataSet

MetadataSection定義在System.ServiceModel.Description命名空間下,用於用於定義基於某種方言(Dialect)的元數據,該類型和WS-MEX中包含元數據SOAP消息主體的<MetadataSection>結點相匹配。我們不妨現在看看MetadataSection的定義:

   1: [XmlRoot(ElementName="MetadataSection", Namespace="https://schemas.xmlsoap.org/ws/2004/09/mex")]
   2: public class MetadataSection
   3: {    
   4:     //其他成員
   5:     public MetadataSection();
   6:     public MetadataSection(string dialect, string identifier, object metadata);   
   7:    
   8:     [XmlAnyAttribute]
   9:     public Collection<XmlAttribute> Attributes { get; }
  10:     [XmlAttribute]
  11:     public string Dialect { get; set; }
  12:     [XmlAttribute]
  13:     public string Identifier { get; set; }
  14:     [XmlElement("Location", typeof(MetadataLocation), Namespace="https://schemas.xmlsoap.org/ws/2004/09/mex")]
  15:     [XmlElement("MetadataReference", typeof(MetadataReference), Namespace="https://schemas.xmlsoap.org/ws/2004/09/mex")]
  16:     [XmlElement("Metadata", typeof(MetadataSet), Namespace="https://schemas.xmlsoap.org/ws/2004/09/mex")]
  17:     [XmlElement("schema", typeof(XmlSchema), Namespace = "https://www.w3.org/2001/XMLSchema")]
  18:     [XmlElement("definitions", typeof(ServiceDescription), Namespace = "https://schemas.xmlsoap.org/wsdl/")]
  19:     [XmlAnyElement]
  20:     public object Metadata { get; set; }   
  21:  
  22:     //四種預定義元數據方言(Dialect)
  23:     //MEX:https://schemas.xmlsoap.org/ws/2004/09/mex
  24:     public static string MetadataExchangeDialect { get; }
  25:     //WS-Policy:https://schemas.xmlsoap.org/ws/2004/09/policy
  26:     public static string PolicyDialect { get; }
  27:     //WSDL:https://schemas.xmlsoap.org/wsdl/
  28:     public static string ServiceDescriptionDialect { get; }
  29:     //XML Schema:https://www.w3.org/2001/XMLSchema
  30:     public static string XmlSchemaDialect { get; } 
  31: }

但看MetadataSection的定義,你可能覺得沒有太多值得關注的地方,如果結合WS-MEX規範,既有很多值得玩味的地方了:

首先,在類型上應用了一個XmlRootAttribute特性,並定義的名稱和命名空間分別為:MetadataSection和https://schemas.xmlsoap.org/ws/2004/09/mex。這和WS-MEX 1.1完全吻合。

其次,屬性Dialect表述元數據方言,你可以定義任意字符串作為其屬性值。在WS-MEX定義了五種預定義元數據方言:MEX、XML Schema、WSDL、WS-Policy和WS-Policy Attachment。除了WS-Policy Attachement,MetadataSection為前麵四種定義了靜態隻讀屬性,以便方麵編程使用。

然後,屬性Identifier表示元數據的標識符,這是一個以URI形式表示的字符串,由於受篇幅所限,在上麵對WS-MEX的介紹中並沒有提及,有興趣的讀者可以參考WS-MEX官方文檔的第4部分。Identifier和Dialect最終被序列化後生成<MetadataSection>元素相應的屬性(Attribute)。此外,MetadataSection還定義了類型為Collection<XmlAttribute>的Attributes屬性,你可以自定義任意的XML屬性,最終將會作為<MetadataSection>元素的屬性。

而元數據的內容通過包含在屬性Metadata中,當整個MetadataSection被序列化後,該屬性的值將會被序列化成一個XML元素,其元素的名稱和命名空間根據具體的類型決定。從應用在該屬性上的一係列XmlElementAttribute特性我們可以看出:MetadataSection為以下幾種特殊的類型定義了相應的名稱和命名空間:

MetadataLocation

MetadataLocation表示以RUI形式表示的元數據文檔的地址,WS-MEX 1.1規定了可以采用元數據文檔地址的URI來替代相應元數據的內容。MetadataLocation定義在System.ServiceModel.Description命名空間下,定義如下:

   1: [XmlRoot(ElementName="Location", Namespace="https://schemas.xmlsoap.org/ws/2004/09/mex")]
   2: public class MetadataLocation
   3: {
   4:     public MetadataLocation();
   5:     public MetadataLocation(string location);
   6:  
   7:     [XmlText]
   8:     public string Location { get; set; }
   9: }

MetadataReference

按照WS-Addressing 2004或者WS-Addressing 1.0規範,如果元數據成為一種可被尋址的資源(Addressable Resource),那麼可以通過終結點引用(Endpoint Reference)的方式來定位該資源。WS-MEX 1.1規定了可以采用元數據終結點引用來替代相應元數據的內容。元數據終結點引用可以通過MetadataReference來表示,MetadataReference定義於System.ServiceModel.Description命名空間下,定義如下:

   1: [XmlRoot(ElementName = "MetadataReference", Namespace = "https://schemas.xmlsoap.org/ws/2004/09/mex")]
   2: public class MetadataReference : IXmlSerializable
   3: {
   4:    
   5:     public MetadataReference();
   6:     public MetadataReference(EndpointAddress address, AddressingVersion addressVersion);  
   7:     public EndpointAddress Address { get; set; }
   8:     public AddressingVersion AddressVersion { get; set; }
   9: }

MetadataSet

MetadataSet就是我們即將要介紹的用於表示MetadataSection集合,將MetadataSet作為MetadataSection的元數據,意味元數據可以以一種嵌套的形式來表示。

XmlSchema

如果元數據的類型為XmlSchema,即表示以XML Schema方言(Dialect)表示的元數據。

ServiceDescription

關於這裏的ServiceDescription,讀者千萬要注意:這裏指的是System.Web.Services.Description.ServiceDescription,而不是System.ServiceModel.Description.ServiceDescription。後者是我們熟悉的對WCF服務的描述(對此不熟悉的讀者,可以參考《WCF技術剖析(卷1)》的第7章),前者實際上是對一個WSDL文檔的描述。由於WSDL的結構相對複雜,ServiceDescription的定義也不太簡單,篇幅所限,本書不會對此作詳細的介紹,有興趣的讀者可以參考MSDN類庫。如果元數據的類型為ServiceDescription,即表示以WSDL方言(Dialect)表示的元數據。

最後,MetadataSection還定義了如下三個靜態方法幫助你快速創建基於WS-Policy策略、XML Schema和WSDL元數據方言的MetadataSection對象:

   1: [XmlRoot(ElementName="MetadataSection", Namespace="https://schemas.xmlsoap.org/ws/2004/09/mex")]
   2: public class MetadataSection
   3: {
   4:    //其他成員
   5:     public static MetadataSection CreateFromPolicy(XmlElement policy, string identifier);
   6:     public static MetadataSection CreateFromSchema(XmlSchema schema);
   7:     public static MetadataSection CreateFromServiceDescription(ServiceDescription serviceDescription);
   8: }

二、 MetdataSet

MetadataSet是WS-MEX 1.1中置於SOAP消息主體部分整個元數據的描述,即對置於SOAP主體部分的<Metadata>所有內容的體現。既然<Metadata>結點是一組<MetadataSection>元素的集合,MetadataSet相應地也就是一組MetadataSection對象的集合,這可以從MetadataSet的定義看出來:

   1: [XmlRoot("Metadata", Namespace="https://schemas.xmlsoap.org/ws/2004/09/mex")]
   2: public class MetadataSet : IXmlSerializable
   3: {
   4:     //其他成員
   5:     public MetadataSet();
   6:     public MetadataSet(IEnumerable<MetadataSection> sections);
   7:  
   8:     [XmlAnyAttribute]
   9:     public Collection<XmlAttribute> Attributes { get; }
  10:     [XmlElement("MetadataSection", Namespace="https://schemas.xmlsoap.org/ws/2004/09/mex")]
  11: public Collection<MetadataSection> MetadataSections { get; }
  12:  
  13:     XmlSchema IXmlSerializable.GetSchema();
  14:     void IXmlSerializable.ReadXml(XmlReader reader);
  15:     void IXmlSerializable.WriteXml(XmlWriter writer);
  16: }

三、WCF元數據架構模型

WCF通過終結點的形式將某個服務暴露出來,而元數據的目的在於幫助服務的消費者如何有效地與該終結點進行交互,以實現對該服務的正常調用。元數據幫助像SvcUtil.exe這樣的代碼生成工具能夠有效地生成客戶端代碼和配置。WCF在內部構建了一個完善的元數據架構體係,很好地實現了元數據的導出、發布、獲取和導入,這個框架體係對元數據的處理大體如圖1所示。

image 圖1 WCF元數據架構體係

圖1可以看出,整個元數據框架體係大體分成服務端體係和客戶端體係,服務端複雜元數據的導出和發布,客戶端實現元數據的獲取與導入。元數據的導出、發布、獲取和導入這4個基本操作在整個框架體係中的分別實現以下的功能:

在後續的文章中,的我們將針對上述的四個元數據基本操作,對WCF的元數據框架的實現原理進行深入地剖析。


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

最後更新:2017-10-30 10:34:37

  上一篇:go  Enterprise Library深入解析與靈活應用(9):個人覺得比較嚴重的關於CachingCallHandler的Bug
  下一篇:go  這是阿裏人的雙11記憶