Example 3-1. The DataContractSerializer

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

namespace WCFServiceProgramming
{
    public abstract class XmlObjectSerializer
    {
        public virtual object ReadObject(Stream stream);
        public virtual object ReadObject(XmlReader reader);

        public virtual void WriteObject(XmlWriter writer, object graph);
        public void WriteObject(Stream stream, object graph);
    }

    public sealed class DataContractSerializer : XmlObjectSerializer
    {
        public DataContractSerializer(Type type);

        //More members
    }
}
View Code

Example 3-2. The generic DataContractSerializer<T>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;

namespace WCFServiceProgramming
{
    public abstract class XmlObjectSerializer
    {
        public virtual object ReadObject(Stream stream);
        public virtual object ReadObject(XmlReader reader);

        public virtual void WriteObject(XmlWriter writer, object graph);
        public void WriteObject(Stream stream, object graph);
    }

    public sealed class DataContractSerializer : XmlObjectSerializer
    {
        public DataContractSerializer(Type type);

        //More members
    }

    public class DataContractSerializer<T> : XmlObjectSerializer
    {
        DataContractSerializer m_DataContractSerializer;

        public DataContractSerializer()
        {
            m_DataContractSerializer = new DataContractSerializer(typeof(T));
        }

        public new T ReadObject(Stream stream)
        {
            return (T)m_DataContractSerializer.ReadObject(stream);
        }

        public new T ReadObject(XmlReader reader)
        {
            return (T)m_DataContractSerializer.ReadObject(reader);
        }

        public void WriteObject(Stream stream, T graph)
        {
            m_DataContractSerializer.WriteObject(stream, graph);
        }

        public void WriteObject(XmlWriter writer, T graph)
        {
            m_DataContractSerializer.WriteObject(writer, graph);
        }

        //More members
    }
}
View Code

Example 3-3. A composite data contract

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace WCFServiceProgramming
{
    [DataContract]
    struct Address
    {
        [DataMember]
        public string Street;

        [DataMember]
        public string City;

        [DataMember]
        public string State;

        [DataMember]
        public string Zip;
    }

    [DataContract]
    struct Contact
    {
        [DataMember]
        public string FirstName;

        [DataMember]
        public string LastName;

        [DataMember]
        public Address Address;
    }
}
View Code

Example 3-4. Applying the serialization event attributes

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace WCFServiceProgramming
{
    [DataContract]
    class MyDataContract
    {
        [OnSerializing]
        void OnSerializing(StreamingContext context)
        {  
        }

        [OnSerialized]
        void OnSerialized(StreamingContext context)
        { 
        }

        [OnDeserializing]
        void OnDeserializing(StreamingContext context)
        { 
        }

        [OnDeserialized]
        void OnDeserialized(StreamingContext context)
        { 
        }

        //Data members
    }
}
View Code

Example 3-5. Initializing nonserializable resources using the deserialized event

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Data;
using System.Data.SqlClient;

namespace WCFServiceProgramming
{
    [DataContract]
    class MyDataContract
    {
        IDbConnection m_Connection;

        [OnDeserialized]
        void OnDeserialized(StreamingContext context)
        {
            m_Connection = new SqlConnection();
        }

        /* Data members */
    }
}
View Code

Example 3-6. Known types in config file

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.runtime.serialization>
    <dataContractSerializer>
      <declaredTypes>
        <add type="Contact,Host,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null">
          <knownType type="Customer,MyClassLibrary,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null"/>
        </add>
      </declaredTypes>
    </dataContractSerializer>
  </system.runtime.serialization>
</configuration>
View Code

Example 3-7. Missing members are initialized to their default value(Server Side)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Diagnostics;

namespace WCFServiceProgramming
{
    /////////////////////////// Service Side //////////////////////////////
    [DataContract]
    struct Contact
    {
        [DataMember]
        public string FirstName;

        [DataMember]
        public string LastName;

        [DataMember]
        public string Address;
    }

    [ServiceContract]
    interface IContactManager
    {
        [OperationContract]
        void AddContact(Contact contact);

        //...
    }

    class ContactManager : IContactManager
    {
        public void AddContact(Contact contact)
        {
            Trace.WriteLine("First name = " + contact.FirstName);
            Trace.WriteLine("Last name = " + contact.LastName);
            Trace.WriteLine("Address = " + (contact.Address ?? "Missing"));

            //...
        }

        //...
    }
}
View Code

Example 3-7. Missing members are initialized to their default value(Client Side)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Channels;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace WCFServiceProgramming
{
    /////////////////////////// Client Side //////////////////////////////
    [DataContract]
    struct Contact
    {
        [DataMember]
        public string FirstName;

        [DataMember]
        public string LastName;
    }

    class ContactManagerClient : ClientBase<IContactManager>, IContactManager
    {
        public void AddContact(Contact contact)
        {
            Channel.AddContact(contact);
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            Contact contact = new Contact();
            contact.FirstName = "Juval";
            contact.LastName = "Lowy";

            ContactManagerClient proxy = new ContactManagerClient();
            proxy.AddContact(contact);

            proxy.Close();
        }
    }
}
View Code

Example 3-8. Implementing IExtensibleDataObject

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace WCFServiceProgramming
{
    [DataContract]
    class Contact : IExtensibleDataObject
    {
        ExtensionDataObject m_ExtensionData;

        public ExtensionDataObject ExtensionData
        {
            get
            {
                return m_ExtensionData;
            }
            set
            {
                m_ExtensionData = value;
            }
        }

        [DataMember]
        public string FirstName;

        [DataMember]
        public string LastName;
    }
}
View Code

Example 3-9. Using an enum in a data contract

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace WCFServiceProgramming
{
    enum ContactType
    {
        Customer,
        Vendor,
        Partner
    }

    [DataContract]
    class Contact 
    {
        [DataMember]
        public ContactType ContactType;

        [DataMember]
        public string FirstName;

        [DataMember]
        public string LastName;
    }
}
View Code

Example 3-10. Type-safe data set and data table

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Collections;
using System.ComponentModel;

namespace WCFServiceProgramming.Library
{
    [Serializable]
    public partial class MyDataSet : DataSet
    {
        [Serializable]
        public partial class ContactsDataTable : DataTable, IEnumerable
        {
            public void AddContactsRow(ContactsRow row);
            public ContactsRow AddContactsRow(string firstName, string lastName);

            public IEnumerator GetEnumerator()
            {
                throw new NotImplementedException();
            }
        }

        public partial class ContactsRow : DataRow
        {
            public string FirstName { get; set; }
            public string LastName { get; set; }
            // More members
        }

    }

    public partial class ContactsTableAdapter : Component
    {
        public virtual MyDataSet.ContactsDataTable GetData();
        // More members
    }
}
View Code

Example 3-11. Using DataTableHelper

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ServiceModel;

namespace WCFServiceProgramming.Library
{
    [DataContract]
    struct Contact
    {
        [DataMember]
        public string FirstName;
        [DataMember]
        public string LastName;
    }

    [ServiceContract]
    interface IContactManager
    {
        [OperationContract]
        Contact[] GetContacts( );
        //...
    }

    class ContactManager : IContactManager
    {
        public Contact[] GetContacts()
        {
            ContactsTableAdapter adapter = new ContactsTableAdapter();
            MyDataSet.ContactsDataTable contactsTable = adapter.GetData();

            Converter<MyDataSet.ContactsRow, Contact> converter;
            converter = delegate(MyDataSet.ContactsRow row)
            {
                Contact contact = new Contact();

                contact.FirstName = row.FirstName;
                contact.LastName = row.LastName;

                return contact;
            };

            return DataTableHelper.ToArray(contactsTable, converter);
        }

        // Rest of the implementation
    }
}
View Code

Example 3-12. The DataTableHelper class

using System;
using System.Collections;
using System.Linq;
using System.Text;
using System.Data;
using System.Diagnostics;
using System.Runtime.Serialization;

namespace WCFServiceProgramming.Library
{
    public static class DataTableHelper
    {
        public static T[] ToArray<R, T>(DataTable table, Converter<R, T> converter) where R : DataRow
        {
            if (table.Rows.Count == 0)
            {
                return new T[] { };
            }

            // Verify [DataContract] or [Serializable] on T
            Debug.Assert(IsDataContract(typeof(T)) || typeof(T).IsSerializable);

            // Verify table contains correct rows
            Debug.Assert(MatchingTableRow<R>(table));

            return System.Collections.UnsafeToArray(table.Rows, converter);
        }

        private static bool IsDataContract(Type type)
        {
            object[] attributes = type.GetCustomAttributes(typeof(DataContractAttribute), false);

            return attributes.Length == 1;
        }

        private static bool MatchingTableRow<R>(DataTable table)
        {
            if (table.Rows.Count == 0)
            {
                return true;
            }

            return table.Rows[0] is R;
        }
    }
}
View Code

Example 3-13. Using bounded generic types

Example 3-14. Marshaling a list as an array

Example 3-15. Marshaling a custom collection as an array

 

posted on 2012-11-22 17:27  逝者如斯(乎)  阅读(212)  评论(0编辑  收藏  举报