Unterstützung von Schemas
WsUtil.exe unterstützt das im XML-Schema angegebene XSD-Schema. xsd-Datei und „wsdl:type“ sollten in der gleichen Kategorie behandelt werden, ausgenommen wenn in „wsdl:type“ ein globales Element eine Parameterliste sein könnte. WsUtil.exe generiert Elementbeschreibungen für alle globalen Elementdefinitionen, die im Serialisierungsmodul verwendet werden können, mit einer zusätzlichen Ausgabe für die in der WSDL-Unterstützung angegebenen Parameterstruktur.
XSD-Schemaunterstützungsebene
WsUtil.exe unterstützt nicht den vollen Umfang des XSD-Schemas. Die aktuelle Supportebene wird auf Schemaunterstützungsebene definiert.
Generierung von Bezeichnern
Der Elementname oder Typname im Schema ist möglicherweise kein gültiger C-Bezeichner, und die Namen werden normalisiert, um gültige C-Namen zu generieren. Ungültige Zeichen im C-Bezeichner werden in den Hexnamen konvertiert, und bei Bedarf kann dem Namen ein Unterstrich „_“ vorangestellt werden. Anonyme Typen werden nach dem umschließenden Elementnamen benannt, jedoch wird ihnen ein Unterstrich „_“ vorangestellt, um Namenskonflikte zu vermeiden. Globale Typnamen werden nach der Normalisierung ungültiger Zeichen unverändert beibehalten. Geschachtelten anonymen Typen wird der Name des übergeordneten Typs vorangestellt.
Für jede globale Elementdefinition generiert wsutil.exe ein WS_ELEMENT_DESCRIPTION-Element in der globalen Beschreibungsstruktur. Für jede globale Typdefinition generiert wsutil.exe eine Typbeschreibung in der globalen Beschreibungsstruktur, auf die die Anwendung verweisen kann.
Für jedes Feld in der Struktur generiert wsutil.exe eine WS_FIELD_DESCRIPTION-Element, das als Teil in die umgebende Struktur eingebettet wird.
Einfache Typen
Werttypen, die in WS_VALUE_TYPE aufgeführt sind, werden als einfache Typen behandelt. Beachten Sie, dass WS_VALUE_TYPE eine echte Teilmenge von WS_TYPE ist. Das Element umfasst grundlegende ganzzahlige und Gleitkomma-Datentypen sowie DECIMAL, WS_DATETIME und UUID.
Im Dienstmodell werden einfache Typen für Eingabeparameter als Wert übergeben, während einfache Typen für Ausgabe- und Ein-/Ausgabeparameter per Verweis übergeben werden.
Wsutil erstellt für globale Elemente, die einfache Typen enthalten eine einfache Elementbeschreibung, wie unten dargestellt.
<xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified"
targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="helloworld" type="xs:int"></xs:element>
</xs:schema>
Wsutil generiert die folgende Elementbeschreibung:
... // global elements
{ // helloworld
{
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.helloworldTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.helloworldTypeNamespace,
WS_INT32_TYPE,
0,
},
}, // helloworld
...
Diese Struktur wird als Teil der globalen Beschreibungsstruktur erzeugt, die in der Headerdatei generiert wird:
typedef struct _example_wsdl
{
WS_ELEMENT_DESCRIPTION helloworld;
} _example_wsdl;
Arrays
Elemente mit maxOccurs größer als 1 oder Sequenzen mit nur einem Element, bei deren untergeordnetem Element maxOccurs größer als 1 ist, werden als Array behandelt. Für ein Arrayelement im Schema generiert wsutil.exe zwei Felder: ein Feld mit der Anzahl, das nicht übertragen wird, und ein Zeigerfeld, das den Arraytyp enthält.
<xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified"
targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="SimpleArray">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="50" name="a" nillable="true" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Die Headerdatei enthält die C-Strukturdefinition für das Array, wobei das Feld aCount die Elementanzahl des Arrays angibt.
typedef struct SimpleArray
{
unsigned int aCount ;
int * a;
} SimpleArray;
Es folgt ein Teil des LocalDefinition-Prototyps, der das Array beschreibt:
... // globalElement part of the LocalDefinitions.
struct // SimpleArray
{
struct // SimpleArray
{
WS_FIELD_DESCRIPTION a;
WS_FIELD_DESCRIPTION * SimpleArrayFields [1];
WS_STRUCT_DESCRIPTION structDesc;
} SimpleArraydescs; // SimpleArray
WS_ELEMENT_DESCRIPTION elementDesc;
} SimpleArray;
// Method with array parameters.
typedef HRESULT (CALLBACK *SimpleMethodCallback)(
const WS_OPERATION_CONTEXT* context,
unsigned int aCount,
int* a,
unsigned int *bCount,
int** b,
unsigned int* cCount,
int** c,
const WS_ASYNC_CONTEXT* asyncContext,
WS_ERROR* error);
HRESULT CALLBACK SimpleMethod (
WS_SERVICE_PROXY* serviceProxy,
WS_HEAP* heap,
unsigned int aCount,
int* a,
unsigned int *bCount,
int** b,
unsigned int* cCount,
int** c,
const WS_ASYNC_CONTEXT* asyncContext,
WS_ERROR* error);
Im Folgenden finden Sie die generierten Definitionen der obigen Beschreibungen. Beachten Sie das WS_REPEATING_ELEMENT_FIELD_MAPPING-Element, das das Feld als Arrayfeld kennzeichnet.
...
{ // SimpleArray
{ // SimpleArray
{ // field description for a
WS_REPEATING_ELEMENT_FIELD_MAPPING,
0,
0,
WS_INT32_TYPE,
0,
WsOffsetOf(SimpleArray, a),
0,
0,
WsOffsetOf(SimpleArray, aCount),
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
}, // end of field description for a
{ // fields description for SimpleArray
(WS_FIELD_DESCRIPTION*)&example_wsdlLocalDefinitions.globalElements.SimpleArray.SimpleArraydescs.a,
},
{
sizeof(SimpleArray),
__alignof(SimpleArray),
(WS_FIELD_DESCRIPTION**)example_wsdlLocalDefinitions.globalElements.SimpleArray.SimpleArraydescs.
SimpleArrayFields,
WsCountOf(example_wsdlLocalDefinitions.globalElements.SimpleArray.SimpleArraydescs.SimpleArrayFields),
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
}, // struct description for SimpleArray
}, // SimpleArray
{
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
WS_STRUCT_TYPE,
(void *)&example_wsdlLocalDefinitions.globalElements.SimpleArray.SimpleArraydescs.structDesc,
},
}, // SimpleArray
...
Wenn das Array ein Parameterfeld in der Eingabe-/Ausgabemeldung ist, würden tatsächlich zwei Parameter für die Methode generiert. Wenn das Array ein Ausgabe- oder Ein-/Ausgabeparameter ist, dann enthält paramStruct für beide Felder eine zusätzliche Ebene der Indirektion.
„Range“ für Array
Wir empfehlen die bewährte Methode, für Arrays nicht maxOccur=„unbounded“ anzugeben. Stattdessen sollte eine feste ganze Zahl angegeben werden, um eine Obergrenze für die zulässige Arrayanzahl festzulegen. „range“ wird für ganzzahlige Typen sowie Zeichenfolgen, Bytearrays und generische Arrays unterstützt.
Heuristik für umschlossene Arrays im Gegensatz zu nicht umschlossenen Arrays
Manchmal werden Arrays von einer anderen Struktur umschlossen, die in eine Struktur der obersten Ebene eingebettet werden soll. In diesem Fall sollten wir die zwischengelagerte Wrapperschicht entfernen. WsUtil.exe generiert den gleichen Prototyp und die gleichen Beschreibungen wie oben beschrieben für SimpleArray.
<xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified"
targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="SimpleArray">
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="50" name="aa" type="xs:int" />
</xs:sequence>
</xs:complexType>
<xs:element name="SimpleArrayWrapper">
<xs:complexType>
<xs:sequence>
<xs:element name="SimpleArray" type="tns:SimpleArray" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
Wsutil erkennt, dass es sich bei SimpleArrayWrapper um einen Wrapper um SimpleArray handelt, und generiert nur die folgenden Strukturen, wobei eine separate Struktur für SimpleArray erstellt wird.
typedef struct SimpleArrayWrapper
{
unsigned int SimpleArrayCount ;
int * SimpleArray;
} SimpleArrayWrapper;
.. // global element inside the LocalDefinitions prototype
struct // SimpleArrayWrapper
{
struct // SimpleArrayWrapper
{
WS_FIELD_DESCRIPTION SimpleArray;
WS_FIELD_DESCRIPTION * SimpleArrayWrapperFields [1];
WS_STRUCT_DESCRIPTION structDesc;
} SimpleArrayWrapperdescs; // SimpleArrayWrapper
WS_ELEMENT_DESCRIPTION elementDesc;
} SimpleArrayWrapper;
...
wsutil.exe generiert die folgenden Definitionen für den entsprechenden Prototyp oben. Beachten Sie, dass in der Feldbeschreibung der Wrappername und der Wrappernamespace-Felder ausgefüllt sind.
... // global element part of the LocalDefinitions structure:
{ // SimpleArrayWrapper
{ // SimpleArrayWrapper
{ // WS_FIELD_DESCRIPTION for SimpleArray
WS_REPEATING_ELEMENT_FIELD_MAPPING,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayWrapperName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayNamespace,
WS_INT32_TYPE,
0,
WsOffsetOf(SimpleArrayWrapper, SimpleArray),
0,
0,
WsOffsetOf(SimpleArrayWrapper, SimpleArrayCount),
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayNamespace,
}, // end of field description for SimpleArray
{ // array of field descriptions for SimpleArrayWrapper
(WS_FIELD_DESCRIPTION *)&example_wsdlLocalDefinitions.globalElements.SimpleArrayWrapper.SimpleArrayWrapperdescs.SimpleArray,
},
{ // WS_STRUCT_DESCRIPTION for SimpleArrayWrapper
sizeof(SimpleArrayWrapper),
__alignof(SimpleArrayWrapper),
(WS_FIELD_DESCRIPTION**)example_wsdlLocalDefinitions.globalElements.SimpleArrayWrapper.SimpleArrayWrapperdescs.SimpleArrayWrapperFields,
WsCountOf(example_wsdlLocalDefinitions.globalElements.SimpleArrayWrapper.SimpleArrayWrapperdescs.SimpleArrayWrapperFields),
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayWrapperTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayNamespace,
}, // struct description for SimpleArrayWrapper
}, // SimpleArrayWrapper
{ // WS_ELEMENT_DESCRIPTION for SimpleArrayWrapper
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayWrapperTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.SimpleArrayNamespace,
WS_STRUCT_TYPE,
(void *)&example_wsdlLocalDefinitions.globalElements.SimpleArrayWrapper.SimpleArrayWrapperdescs.structDesc,
},
}, // SimpleArrayWrapper
Strukturen
Ein komplexer Typ (complexType) mit mehreren Elementen in einer Sequenz ist eine Struktur. Ein auf ein Objekt angewendeter
<xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified"
targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="StructType">
<xs:sequence>
<xs:element minOccurs="0" name="FirstName" nillable="true" type="xs:string" />
<xs:element minOccurs="0" name="LastName" nillable="true" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="StructType" nillable="true" type="tns:StructType" />
</xs:schema>
Wsutil.exe generiert einen Strukturprototyp als:
struct StructType
{
WS_STRING FirstName;
WS_STRING LastName;
};
// methods using structure parameters.
typedef HRESULT (CALLBACK *SimpleMethodCallback) (
const WS_OPERATION_CONTEXT* context,
StructType* a,
StructType** b,
StructType** c,
const WS_ASYNC_CONTEXT* asyncContext,
WS_ERROR* error);
HRESULT CALLBACK SimpleMethod (WS_SERVICE_PROXY* serviceProxy,
WS_HEAP* heap,
StructType* a,
StructType** b,
StructType** c,
const WS_ASYNC_CONTEXT* asyncContext,
WS_ERROR* error);
wsutil generiert den folgenden Prototyp für LocalDefinition:
struct // StructType
{
struct // StructType
{
WS_FIELD_DESCRIPTION FirstName;
WS_FIELD_DESCRIPTION LastName;
WS_FIELD_DESCRIPTION * StructTypeFields [2];
WS_STRUCT_DESCRIPTION structDesc;
} StructTypedescs; // StructType
WS_ELEMENT_DESCRIPTION elementDesc;
}
Die Definition für die Struktur sieht wie unten aus, wobei die Struktur zwei Feldbeschreibungen enthält.
// global element inside LocalDefinitions.
{ // StructType
{ // StructType
{ // field description for FirstName
WS_ELEMENT_FIELD_MAPPING,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.FirstNameLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.FirstNameNamespace,
WS_STRING_TYPE,
0,
WsOffsetOf(StructType, FirstName),
0,
0,
}, // end of field description for FirstName
{ // field description for LastName
WS_ELEMENT_FIELD_MAPPING,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.LastNameLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.FirstNameNamespace,
WS_STRING_TYPE,
0,
WsOffsetOf(StructType, LastName),
0,
0,
}, // end of field description for LastName
{ // fields description for StructType
(WS_FIELD_DESCRIPTION *)&example_wsdlLocalDefinitions.globalElements.StructType.StructTypedescs.FirstName,
(WS_FIELD_DESCRIPTION *)&example_wsdlLocalDefinitions.globalElements.StructType.StructTypedescs.LastName,
},
{ // WS_STRUCT_DESCRIPTION for StructType
sizeof(StructType),
__alignof(StructType),
(WS_FIELD_DESCRIPTION**)example_wsdlLocalDefinitions.globalElements.StructType.StructTypedescs.StructTypeFields,
WsCountOf(example_wsdlLocalDefinitions.globalElements.StructType.StructTypedescs.StructTypeFields),
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.StructTypeTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.FirstNameNamespace,
}, // struct description for StructType
}, // StructType
{
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.StructTypeTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.FirstNameNamespace,
WS_STRUCT_TYPE,
(void *)&example_wsdlLocalDefinitions.globalElements.StructType.StructTypedescs.structDesc,
},
}, // StructType
Zur Unterstützung der Erweiterbarkeit werden eingebettete Strukturen immer per Verweis übergeben. Im Dienst werden alle out- oder in,out-Strukturen per double-Zeiger übergeben, um eine zukünftige Erweiterung der Struktur sowie eine Struktur, die NULL-Wert enthalten kann, zu ermöglichen.
Rekursive Strukturen
Rekursive Strukturen werden unterstützt, und die eingebetteten Typen werden per Verweis übergeben. Für folgendes wsdl gilt:
<xs:schema xmlns:tns="http://Example.org" elementFormDefault="qualified"
targetNamespace="http://Example.org" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="SimpleMethod">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" name="a" type="xs:int" />
<xs:element minOccurs="0" name="b" type="tns:example" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="example">
<xs:sequence>
<xs:element minOccurs="0" name="d" type="tns:example" />
<xs:element minOccurs="0" name="c" type="xs:int" />
</xs:sequence>
</xs:complexType>
</xs:schema>
Wsutil erzeugt die folgenden Typdefinitionen sowie die Typbeschreibungen:
typedef struct example
{
struct example * d;
int32 c;
} example;
typedef struct SimpleMethod
{
unsigned __int32 a;
struct example * b;
} SimpleMethod;
// global element part of the LocalDefinitions.
...
struct // SimpleMethod
{
struct // SimpleMethod
{
WS_FIELD_DESCRIPTION a;
struct // example
{
WS_FIELD_DESCRIPTION d;
WS_FIELD_DESCRIPTION c;
WS_FIELD_DESCRIPTION * exampleFields [2];
WS_STRUCT_DESCRIPTION structDesc;
} exampledescs; // example
WS_FIELD_DESCRIPTION b;
WS_FIELD_DESCRIPTION * SimpleMethodFields [2];
WS_STRUCT_DESCRIPTION structDesc;
} SimpleMethoddescs; // SimpleMethod
WS_ELEMENT_DESCRIPTION elementDesc;
} SimpleMethod;
...
Die Definition wird wie folgt generiert:
{ // SimpleMethod
{ // field description for a
WS_ELEMENT_FIELD_MAPPING,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
WS_INT32_TYPE,
0,
WsOffsetOf(SimpleMethod, a),
0,
0,
}, // end of field description for a
{ // example
{ // field description for d
WS_ELEMENT_FIELD_MAPPING,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.dLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
WS_STRUCT_TYPE,
(WS_STRUCT_DESCRIPTION*)&example_wsdlLocalDefinitions.globalElements.SimpleMethod.SimpleMethoddescs.structDesc,
WsOffsetOf(example, d),
WS_FIELD_POINTER,
0,
}, // end of field description for d
{ // field description for c
WS_ELEMENT_FIELD_MAPPING,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.cLocalName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
WS_INT32_TYPE,
0,
WsOffsetOf(example, c),
0,
0,
}, // end of field description for c
{ // fields description for example
(WS_FIELD_DESCRIPTION *)&example_wsdlLocalDefinitions.globalElements.SimpleMethod.SimpleMethoddescs.exampledescs.d,
(WS_FIELD_DESCRIPTION *)&example_wsdlLocalDefinitions.globalElements.SimpleMethod.SimpleMethoddescs.exampledescs.c,
},
{
sizeof(example),
__alignof(example),
(WS_FIELD_DESCRIPTION**)example_wsdlLocalDefinitions.globalElements.SimpleMethod.SimpleMethoddescs.exampledescs.exampleFields,
WsCountOf(example_wsdlLocalDefinitions.globalElements.SimpleMethod.SimpleMethoddescs.exampledescs.exampleFields),
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.exampleTypeName,
(WS_XML_STRING*)&example_wsdlLocalDefinitions.dictionary.xmlStrings.aNamespace,
}, // struct description for example
}
Strukturvererbung
wsutil unterstützt komplexe Typerweiterungen, wobei ein komplexer Typ eine Erweiterung eines anderen komplexen Typs ist.
<s:schema xmlns:tns="http://Example.org" elementFormDefault="qualified"
targetNamespace="http://Example.org" xmlns:s="http://www.w3.org/2001/XMLSchema">
<s:complexType name="LinkList">
<s:sequence>
<s:element minOccurs="0" name="d" type="tns:LinkList" />
<s:element minOccurs="0" name="c" type="s:int" />
</s:sequence>
</s:complexType>
<s:element name="DerivedLinkList">
<s:complexType>
<s:complexContent>
<s:extension base="tns:LinkList">
<s:sequence>
<s:element name="derive1" type="s:int" />
</s:sequence>
</s:extension>
</s:complexContent>
</s:complexType>
</s:element>
</s:schema>
Das obige xsd-Fragment gibt an, dass DerivedLinkList von LinkList abgeleitet ist.
Wsutil.exe generiert Hilfsroutinen für C und C++, damit die Anwendung die Typinformationen des Basistyps und der abgeleiteten Typen leicher einrichten kann. Im folgenden Code wird das Makro _WS_CPLUSPLUS verwendet, um die Definition für die Sprachen C und C++ zu unterscheiden:
#if defined(_WS_CPLUSPLUS)
typedef struct LinkList
{
LinkList();
LinkList(WS_STRUCT_DESCRIPTION*);
struct _DerivedLinkList* WINAPI As_DerivedLinkList();
const struct _WS_STRUCT_DESCRIPTION* _type;
struct LinkList * d;
int c;
} LinkList;
#endif
#if !defined(_WS_CPLUSPLUS)
typedef struct LinkList
{
const struct _WS_STRUCT_DESCRIPTION* _type;
struct LinkList * d;
int c;
} LinkList;
void WINAPI LinkList_Init(LinkList*);
#endif
#if defined(_WS_CPLUSPLUS)
typedef struct _DerivedLinkList:LinkList
{
_DerivedLinkList();
int derive1;
} _DerivedLinkList;
#endif
#if !defined(_WS_CPLUSPLUS)
typedef struct _DerivedLinkList
{
struct LinkList _base;
int derive1;
} _DerivedLinkList;
struct _DerivedLinkList* WINAPI LinkList_As_DerivedLinkList(LinkList*);
#endif
In der Hilfsroutine im Stil von C ruft die Anwendung vor der Serialisierung die von wsutil generierte Routine LinkList_Init auf, um die Struktur zu initialisieren und die Typbeschreibung auf die Beschreibung des LinkList-Typs festzulegen. Nach der Deserialisierung kann die Anwendung mit einem Aufruf von LinkList_As_DerivedLinkList den abgeleiteten Typ abrufen.
Um Typinformationen zur Laufzeit abzurufen, generiert wsutil das erste Feld des Basistyps mit dem TypWS_STRUCT_DESCRIPTION* und der Feldzuordnung WS_TYPE_ATTRIBUTE_FIELD_MAPPING zur Beschreibung der xsi:type-Informationen. Die Anwendung kann das Feld direkt festlegen oder überprüfen, um den tatsächlichen Typ der Strukturen zu ermitteln. Der folgende Code legt beispielsweise den Typ der Struktur auf DrivedLinkList fest:
_DerivedLinkList derivedLinkList;
derivedLinkList._base._type = (WS_STRUCT_DESCRIPTION*)test_xsd.globalElements.DerivedLinkList.typeDescription;
WsWriteType(
writer,
WS_ELEMENT_TYPE_MAPPING,
WS_STRUCT_TYPE,
(WS_STRUCT_DESCRIPTION*)test_xsd.globalElements.DerivedLinkList.typeDescription,
...);
Nachdem die Struktur deserialisiert wurde, kann die Anwendung die Typbeschreibung direkt vergleichen, um den deserialisierten Typ zu ermitteln:
if (derviedLinkList._base._type == (WS_STRUCT_DESCRIPTION*)test_xsd.globalElements.DerivedLinkList.typeDescription)
{
// the deserialized type is of type _DerivedLinkList
...
}
Wsutil erzeugt sowohl für die Basisstruktur als auch für die abgeleitete Struktur eine Klasse. Der Standardkonstruktor initialisiert den Typ und die entsprechende Typbeschreibung. Die AsDerivedType-Routine hilft dabei, sichere Typenzuwandlungen zwischen Typen durchzuführen.
{ // field description for typeOfLinkList
WS_TYPE_ATTRIBUTE_FIELD_MAPPING,
0,
0,
WS_DESCRIPTION_TYPE,
0,
WsOffsetOf(LinkList, typeOfLinkList),
0,
0,
}, // end of field description for typeOfLinkList ...
{
sizeof(LinkList),
__alignof(LinkList),
(WS_FIELD_DESCRIPTION**)&test_xsdLocalDefinitions.globalTypes.LinkListdescs.LinkListFields,
WsCountOf(test_xsdLocalDefinitions.globalTypes.LinkListdescs.LinkListFields),
(WS_XML_STRING*)&test_xsdLocalDefinitions.dictionary.xmlStrings.LinkListTypeName,
(WS_XML_STRING*)&test_xsdLocalDefinitions.dictionary.xmlStrings.LinkListTypeNamespace,
0,
(WS_STRUCT_DESCRIPTION**)&test_xsdLocalDefinitions.globalTypes.LinkListdescs.SubTypes,
1,
}, // struct description for LinkList
nillable
Das nillable-Attribut wird für Zeichenfolgen, Strukturen und Bytearrays unterstützt. Das WS_FIELD_NILLABLE-Attribut wird Feldern mit einem nillable-Attribut hinzugefügt. Der Zeiger wird auf NULL festgelegt, wenn ein Element einen NULL-Wert enthalten kann. Felder mit einem nillable-Attribut in einer Struktur werden als Zeiger behandelt. Eine Parameterstruktur mit einem nillable-Attribut wird per Verweis übergeben.
Zeiger
Werttypen müssen als Wert oder bei Ausgabeparametern als Verweis übergeben werden. Double-Zeiger sind nur für reine out-Strukturen zulässig.
Parameterlos
Erinnern Sie sich an unsere vorherige Diskussion über den Namen „Parameters“ für den Meldungsteil. Wenn dies angegeben wird, versuchen wir, einen kombinierten Frame für die Eingabe- und Ausgabemeldung für den resultierenden Dienstvorgang zu generieren. Fehlt diese Angabe, würde der resultierende Dienstvorgang Eingabe- und Ausgabemeldungen als Strukturen als Parameter enthalten.
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:tns="http://Sapphire.org"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing" xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
xmlns:wsap="http://schemas.xmlsoap.org/ws/2004/08/addressing/policy" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:msc="http://schemas.microsoft.com/ws/2005/12/wsdl/contract" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl"
xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:wsa10="http://www.w3.org/2005/08/addressing"
xmlns:wsx="http://schemas.xmlsoap.org/ws/2004/09/mex" targetNamespace="http://Sapphire.org"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<wsdl:message name="ISimpleService_SimpleMethod_InputMessage">
<wsdl:part name="noparameters" element="tns:SimpleMethod" />
</wsdl:message>
<wsdl:message name="ISimpleService_SimpleMethod_OutputMessage">
<wsdl:part name="noparameters" element="tns:SimpleMethodResponse" />
</wsdl:message>
</wsdl:definitions>
Daher sieht bei unserem SimpleMethod-Vorgang die Signatur für den Dienst und den Client wie folgt aus.
typedef HRESULT (CALLBACK *SimpleMethodCallback)
(const WS_OPERATION_CONTEXT* context,
SimpleMethodRequest* inMessage,
SimpleMethodResponse** outMessage,
const WS_ASYNC_CONTEXT* asyncContext,
WS_ERROR* error);
HRESULT CALLBACK SimpleMethod (
WS_SERVICE_PROXY* serviceProxy,
WS_HEAP* heap,
SimpleMethodRequest* inMessage,
SimpleMethodResponse** outMessage,
const WS_ASYNC_CONTEXT* asyncContext,
WS_ERROR* error);
Sicherheit
Weitere Informationen finden Sie im Abschnitt „Sicherheit“ unter Wsutil-Compilertool sowie unter Serialisierung.