There’s another form
of XML serialization, which may seem redundant at first.
You’ll recall that runtime serialization was able to
encode an object using SOAP. The SoapFormatter
produced a SOAP stream that was optimized for recreating the original
object in another .NET application; specifically, the object and all
its members were encoded using CLR types. A non-.NET application
reading that SOAP stream would most likely have no idea what to do
with the data.
However, the
XmlSerializer
can also serialize an object to
SOAP, with an emphasis on the standard SOAP encodings. With SOAP
serialization, you get all the interoperability of XML, with
additional CLR awareness. The key to standards-compliant SOAP
serialization is the SoapReflectionImporter
class.
The .NET Framework SDK Documentation will
tell you that SoapReflectionImporter
is reserved
for internal use, and should not be used by your application.
However, it does have one constructor and one method that you can use
to serialize objects to SOAP.
The code in Example 9-9 demonstrates how to
serialize the personnel records from earlier examples to SOAP, using
the same Personnel
class and the
CreatePersonnel( )
method from before.
public static void Main(string [ ] args) { Personnel personnel = CreatePersonnel( ); SoapReflectionImporter importer = new SoapReflectionImporter( ); XmlTypeMapping mapping = importer.ImportTypeMapping(typeof(Personnel)); XmlSerializer serializer = new XmlSerializer(mapping); using (StreamWriter stream = File.CreateText("PersonnelSoap2.xml")) { XmlTextWriter writer = new XmlTextWriter(stream); writer.Formatting = Formatting.Indented; writer.WriteStartElement("AngusHardware"); serializer.Serialize(writer,personnel); writer.WriteEndElement( ); } }
The object will be serialized to the XML shown below:
<AngusHardware> <Personnel xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/ 2001/XMLSchema-instance" id="id1"> <Employees href="#id2" /> </Personnel> <q1:Array id="id2" q1:arrayType="Employee[1]" xmlns:q1="http://schemas.xmlsoap.org/ soap/encoding/"> <Item href="#id3" /> </q1:Array> <Employee id="id3" d2p1:type="Employee" xmlns:d2p1="http://www.w3.org/2001/XMLSchema- instance"> <FirstName xmlns:q2="http://www.w3.org/2001/XMLSchema" d2p1:type="q2:string"> Niel</FirstName> <MiddleInitial xmlns:q3="http://www.w3.org/2001/XMLSchema" d2p1:type="q3:string" >M</MiddleInitial> <LastName xmlns:q4="http://www.w3.org/2001/XMLSchema" d2p1:type="q4:string" >Bornstein</LastName> <Addresses href="#id4" /> <HireDate xmlns:q5="http://www.w3.org/2001/XMLSchema" d2p1:type="q5:dateTime"> 2001-01-01T00:00:00.0000000-05:00</HireDate> </Employee> <q6:Array id="id4" q6:arrayType="Address[1]" xmlns:q6="http://schemas.xmlsoap.org/ soap/encoding/"> <Item href="#id5" /> </q6:Array> <Address id="id5" d2p1:type="Address" xmlns:d2p1="http://www.w3.org/2001/XMLSchema- instance"> <AddressType d2p1:type="AddressType">Home</AddressType> <Street href="#id6" /> <City xmlns:q7="http://www.w3.org/2001/XMLSchema" d2p1:type="q7:string" >Atlanta</City> <State d2p1:type="State">GA</State> <Zip xmlns:q8="http://www.w3.org/2001/XMLSchema" d2p1:type="q8:string">30037 </Zip> </Address> <q9:Array id="id6" xmlns:q10="http://www.w3.org/2001/XMLSchema" q9:arrayType="q10: string[1]" xmlns:q9="http://schemas.xmlsoap.org/soap/encoding/"> <Item>999 Wilford Trace</Item> </q9:Array> </AngusHardware>
That’s not very pretty. Fortunately, just as there are attributes that affect the serialization of an object to XML, there are attributes that affect the serialization of an object to SOAP. Table 9-3 lists them, with their descriptions.
Attribute name |
Description |
|
Place this attribute on a member to indicate that it is to be serialized as a SOAP attribute. |
|
Place this attribute on a member to indicate that it is to be serialized as a SOAP element. |
|
Place this attribute on a member that returns an enumeration type to indicate how it is to be serialized to SOAP. |
|
Place this attribute on a member to indicate that it is not to be serialized to SOAP. |
|
Place this attribute on a member to have
|
|
Place this attribute on a class to indicate that the class is to be included in the generated XML Schema definition. |
Just as with XML attributes, you
can override the SOAP attributes that affect serialization at
runtime. To make the Personnel
object serialize a
little more sensibly, you can either add the attributes to the
Personnel type’s source code, or you can add them
using the SoapAttributeOverrides
class.
The use of
SoapAttributeOverrides
is similar to
XmlAttributeOverrides
. Rather than go into extreme
detail, I’ll just show you the code, again with the
changes highlighted:
Personnel personnel = CreatePersonnel( ); SoapAttributeOverrides overrides = new SoapAttributeOverrides( ); SoapAttributes attributes = new SoapAttributes( ); attributes.SoapElement = new SoapElementAttribute("employees"); overrides.Add(typeof(Personnel), "Employees", attributes); SoapReflectionImporter importer = new SoapReflectionImporter(overrides); XmlTypeMapping mapping = importer.ImportTypeMapping(typeof(Personnel)); XmlSerializer serializer = new XmlSerializer(mapping); using (StreamWriter stream = File.CreateText("PersonnelSoap2.xml")) { XmlTextWriter writer = new XmlTextWriter(stream); writer.Formatting = Formatting.Indented; writer.WriteStartElement("AngusHardware"); serializer.Serialize(writer,personnel); writer.WriteEndElement( ); }
The
only changes effected by the
SoapAttributeOverrides
in this example is to
change the name of the Employees
element to
employees
, as shown here:
<AngusHardware> <Personnel xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/ 2001/XMLSchema-instance" id="id1"> <employees href="#id2" /> </Personnel> ... </AngusHardware>
18.117.99.152