HOW TO:序列化 WCF 應用程式中的訊息

更新:2007 年 11 月

.NET Compact Framework 3.5 版加入了 XmlObjectSerializer 類別的支援,此類別可用來實作序列化和還原序列化 Windows Communication Foundation (WCF) 應用程式中訊息的支援。

範例

下列程式碼範例顯示名為 CFMessagingSerializer 的類別,這個類別會實作 XmlObjectSerializer,而且可在裝置和桌上型電腦使用來序列化和還原序列化訊息。

Public Class CFMessagingSerializer
    Inherits XmlObjectSerializer

    Private objectType As Type

    Private serializer As XmlSerializer

    Public Sub New(ByVal objectType As Type)
        Me.New(objectType, Nothing, Nothing)

    End Sub

    Public Sub New(ByVal objectType As Type, ByVal wrapperName As String, ByVal wrapperNamespace As String)
        MyBase.New()
        If (objectType Is Nothing) Then
            Throw New ArgumentNullException("objectType")
        End If
        If ((wrapperName Is Nothing) _
                    <> (wrapperNamespace = Nothing)) Then
            Throw New ArgumentException("wrapperName and wrapperNamespace must be either both null or both non-null.")
        End If
        If (wrapperName = String.Empty) Then
            Throw New ArgumentException("Cannot be the empty string.", "wrapperName")
        End If
        Me.objectType = objectType
        If (Not (wrapperName) Is Nothing) Then
            Dim root As XmlRootAttribute = New XmlRootAttribute(wrapperName)
            root.Namespace = wrapperNamespace
            Me.serializer = New XmlSerializer(objectType, root)
        Else
            Me.serializer = New XmlSerializer(objectType)
        End If
    End Sub

    Public Overrides Function IsStartObject(ByVal reader As XmlDictionaryReader) As Boolean
        Throw New NotImplementedException
    End Function

    Public Overrides Function ReadObject(ByVal reader As XmlDictionaryReader, ByVal verifyObjectName As Boolean) As Object
        Debug.Assert((Not (serializer) Is Nothing))
        If (reader Is Nothing) Then
            Throw New ArgumentNullException("reader")
        End If
        If Not verifyObjectName Then
            Throw New NotSupportedException
        End If
        Return serializer.Deserialize(reader)
    End Function

    Public Overrides Sub WriteStartObject(ByVal writer As XmlDictionaryWriter, ByVal graph As Object)
        Throw New NotImplementedException
    End Sub

    Public Overrides Sub WriteObjectContent(ByVal writer As XmlDictionaryWriter, ByVal graph As Object)
        If (writer Is Nothing) Then
            Throw New ArgumentNullException("writer")
        End If
        If (writer.WriteState <> WriteState.Element) Then
            Throw New SerializationException(String.Format("WriteState '{0}' not valid. Caller must write start element before serializing in contentOnly mode.", writer.WriteState))
        End If
        Dim memoryStream As MemoryStream = New MemoryStream
        Dim bufferWriter As XmlDictionaryWriter = XmlDictionaryWriter.CreateTextWriter(memoryStream, Encoding.UTF8)
        serializer.Serialize(bufferWriter, graph)
        bufferWriter.Flush()
        memoryStream.Position = 0
        Dim reader As XmlReader = New XmlTextReader(memoryStream)
        reader.MoveToContent()
        writer.WriteAttributes(reader, False)
        If reader.Read Then

            While (reader.NodeType <> XmlNodeType.EndElement)
                writer.WriteNode(reader, False)

            End While
            ' this will take us to the start of the next child node, or the end node.
            reader.ReadEndElement()
            ' not necessary, but clean
        End If
    End Sub

    Public Overrides Sub WriteEndObject(ByVal writer As XmlDictionaryWriter)
        Throw New NotImplementedException
    End Sub

    Public Overrides Sub WriteObject(ByVal writer As XmlDictionaryWriter, ByVal graph As Object)
        Debug.Assert((Not (serializer) Is Nothing))
        If (writer Is Nothing) Then
            Throw New ArgumentNullException("writer")
        End If
        serializer.Serialize(writer, graph)
    End Sub
End Class
public class CFMessagingSerializer : XmlObjectSerializer
{
    readonly Type objectType;
    XmlSerializer serializer;

    public CFMessagingSerializer(Type objectType)
        : this(objectType, null, null)
    {
    }

    public CFMessagingSerializer(Type objectType, string wrapperName, string wrapperNamespace)
    {
        if (objectType == null)
            throw new ArgumentNullException("objectType");
        if ((wrapperName == null) != (wrapperNamespace == null))
            throw new ArgumentException("wrapperName and wrapperNamespace must be either both null or both non-null.");
        if (wrapperName == string.Empty)
            throw new ArgumentException("Cannot be the empty string.", "wrapperName");

        this.objectType = objectType;
        if (wrapperName != null)
        {
            XmlRootAttribute root = new XmlRootAttribute(wrapperName);
            root.Namespace = wrapperNamespace;
            this.serializer = new XmlSerializer(objectType, root);
        }
        else
            this.serializer = new XmlSerializer(objectType);
    }

    public override bool IsStartObject(XmlDictionaryReader reader)
    {
        throw new NotImplementedException();
    }

    public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
    {
        Debug.Assert(serializer != null);
        if (reader == null) throw new ArgumentNullException("reader");
        if (!verifyObjectName)
            throw new NotSupportedException();

        return serializer.Deserialize(reader);
    }

    public override void WriteStartObject(XmlDictionaryWriter writer, object graph)
    {
        throw new NotImplementedException();
    }

    public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
    {
        if (writer == null) throw new ArgumentNullException("writer");
        if (writer.WriteState != WriteState.Element)
            throw new SerializationException(string.Format("WriteState '{0}' not valid. Caller must write start element before serializing in contentOnly mode.",
                writer.WriteState));
        using (MemoryStream memoryStream = new MemoryStream())
        {
            using (XmlDictionaryWriter bufferWriter = XmlDictionaryWriter.CreateTextWriter(memoryStream, Encoding.UTF8))
            {
                serializer.Serialize(bufferWriter, graph);
                bufferWriter.Flush();
                memoryStream.Position = 0;
                using (XmlReader reader = new XmlTextReader(memoryStream))
                {
                    reader.MoveToContent();
                    writer.WriteAttributes(reader, false);
                    if (reader.Read()) // move off start node (we want to skip it)
                    {
                        while (reader.NodeType != XmlNodeType.EndElement) // also skip end node.
                            writer.WriteNode(reader, false); // this will take us to the start of the next child node, or the end node.
                        reader.ReadEndElement(); // not necessary, but clean
                    }
                }
            }
        }
    }

    public override void WriteEndObject(XmlDictionaryWriter writer)
    {
        throw new NotImplementedException();
    }

    public override void WriteObject(XmlDictionaryWriter writer, object graph)
    {
        Debug.Assert(serializer != null);
        if (writer == null) throw new ArgumentNullException("writer");
        serializer.Serialize(writer, graph);
    }
}

編譯程式碼

此範例需要下列命名空間的參考:

請參閱

其他資源

Windows Communication Foundation (WCF) 開發和 .NET Compact Framework