WCF技术剖析之二十五:元数据(Metadata)架构体系全景展现[元数据描述篇]2012-11-22 博客园 蒋金楠在[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>元素集合有相应的类型来表示,那就是我们接下来要着重介绍的MetadataSection和MetadataSet。一、MetadataSectionMetadataSection定义在System.ServiceModel.Description命名空间下,用于用于定义基于某种方言(Dialect)的元数据,该类型和WS-MEX中包含元数据SOAP消息主体的<MetadataSection>结点相匹配。我们不妨现在看看MetadataSection的定义:
1: [XmlRoot(ElementName="MetadataSection", Namespace="http://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="http://schemas.xmlsoap.org/ws/2004/09/mex")]
15: [XmlElement("MetadataReference", typeof(MetadataReference), Namespace="http://schemas.xmlsoap.org/ws/2004/09/mex")]
16: [XmlElement("Metadata", typeof(MetadataSet), Namespace="http://schemas.xmlsoap.org/ws/2004/09/mex")]
17: [XmlElement("schema", typeof(XmlSchema), Namespace = "http://www.w3.org/2001/XMLSchema")]
18: [XmlElement("definitions", typeof(ServiceDescription), Namespace = "http://schemas.xmlsoap.org/wsdl/")]
19: [XmlAnyElement]
20: public object Metadata { get; set; }
21:
22: //四种预定义元数据方言(Dialect)
23: //MEX:http://schemas.xmlsoap.org/ws/2004/09/mex
24: public static string MetadataExchangeDialect { get; }
25: //WS-Policy:http://schemas.xmlsoap.org/ws/2004/09/policy
26: public static string PolicyDialect { get; }
27: //WSDL:http://schemas.xmlsoap.org/wsdl/
28: public static string ServiceDescriptionDialect { get; }
29: //XML Schema:http://www.w3.org/2001/XMLSchema
30: public static string XmlSchemaDialect { get; }
31: }
但看MetadataSection的定义,你可能觉得没有太多值得关注的地方,如果结合WS-MEX规范,既有很多值得玩味的地方了:首先,在类型上应用了一个XmlRootAttribute特性,并定义的名称和命名空间分别为:MetadataSection和http://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为以下几种特殊的类型定义了相应的名称和命名空间:MetadataLocationMetadataLocation表示以RUI形式表示的元数据文档的地址,WS-MEX 1.1规定了可以采用元数据文档地址的URI来替代相应元数据的内容。MetadataLocation定义在System.ServiceModel.Description命名空间下,定义如下:
1: [XmlRoot(ElementName="Location", Namespace="http://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 = "http://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: }