Flylib.com

Books Software

 
 
 

2.11 Create a Strongly Typed Collection


2.11 Create a Strongly Typed Collection

Problem

You need to create a collection that can hold elements only of a specific type.

Solution

Create a class that derives from the System.Collections.CollectionBase or System.Collections.DictionaryBase classes, and implement type-safe methods for the manipulation of the collection.

Discussion

The CollectionBase and DictionaryBase classes provide convenient base classes from which to derive type-safe collections without having to implement the standard IDictionary , IList , ICollection , and IEnumerable interfaces from scratch.

CollectionBase is for IList -based collections (such as ArrayList ). Internally, CollectionBase maintains the collection using a standard ArrayList object, which is accessible through the protected property List . DictionaryBase is for IDictionary -based collections (such as Hashtable ). Internally, DictionaryBase maintains the collection using a standard Hashtable object, which is accessible through the protected property Dictionary . The following code shows the implementation of a strongly typed collection (based on the CollectionBase class) to represent a list of System.Reflection.AssemblyName objects.

using System.Reflection;
using System.Collections;

public class AssemblyNameList : CollectionBase {

    public int Add(AssemblyName value) {

        return this.List.Add(value);
    }

    public void Remove(AssemblyName value) {

        this.List.Remove(value);
    }

    public AssemblyName this[int index] { 

        get {
            return (AssemblyName)this.List[index];
        }

        set {
            this.List[index] = value;
        }
    }

    public bool Contains(AssemblyName value) {

        return this.List.Contains(value);
    }

    public void Insert(int index, AssemblyName value) {

        this.List.Insert(index, value);
    }
}

Both the CollectionBase and DictionaryBase classes implement a set of protected methods with the prefix On *. These methodssuch as OnClear , OnClearComplete , OnGet , OnGetComplete , and so onare intended to be overridden by a derived class and allow you to implement any custom functionality necessary to manage the strongly typed collection. The CollectionBase and DictionaryBase classes call the appropriate method before and after modifications are made to the underlying collection through the List or Dictionary properties.



2.12 Store a Serializable Object to a File

Problem

You need to store a serializable object and its state to a file and then deserialize it later.

Solution

Use a formatter to serialize the object and write it to a System.IO.FileStream . When you need to retrieve the object, use the same type of formatter to read the serialized data from the file and deserialize the object. The .NET Framework class library includes the following formatter implementations for serializing objects to binary or SOAP format:

  • System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

  • System.Runtime.Serialization.Formatters.Soap.SoapFormatter

Discussion

Using the BinaryFormatter and SoapFormatter classes, you can serialize an instance of any type that's decorated with the attribute System.SerializableAttribute . The BinaryFormatter produces a binary data stream representing the object and its state, whereas the SoapFormatter produces a SOAP document.

Both the BinaryFormatter and SoapFormatter classes implement the interface System.Runtime.Serialization.IFormatter , which defines two methods : Serialize and Deserialize . The Serialize method takes a System.IO.Stream reference and a System.Object reference as arguments, serializes the Object , and writes it to the Stream . The Deserialize method takes a Stream reference as an argument, reads the serialized object data from the Stream , and returns an Object reference to a deserialized object. You must cast the returned Object reference to the correct type.

Important  

To call the Serialize and Deserialize methods of the BinaryFormatter class, your code must be granted the SerializationFormatter element of the permission System.Security.Permissions.SecurityPermission .

To call the Serialize and Deserialize methods of the SoapFormatter class, your code must be granted full trust because the System.Runtime.Serialization.Formatters.Soap.dll assembly in which the SoapFormatter class is declared does not allow partially trusted callers . Refer to recipe 13.1 for more information about assemblies and partially trusted callers .

The BinarySerializationExample class listed here demonstrates the use of a BinaryFormatter to serialize a System.Collections.ArrayList containing a list of people to a file. The ArrayList is then deserialized from the file and the contents displayed to the console.

using System.IO;
using System.Collections;
using System.Runtime.Serialization.Formatters.Binary;

public class BinarySerializationExample {

    public static void Main() {
        
        // Create and configure the ArrayList to serialize
        ArrayList people = new ArrayList();
        people.Add("Graeme");
        people.Add("Lin");                    
        people.Add("Andy");

        // Serialize the ArrayList object
        FileStream str = File.Create("people.bin");
        BinaryFormatter bf = new BinaryFormatter();
        bf.Serialize(str, people);
        str.Close();
        
        // Deserialize the ArrayList object
        str = File.OpenRead("people.bin");
        bf = new BinaryFormatter();
        people = (ArrayList)bf.Deserialize(str);
        str.Close();
        
        // Display the contents of the deserialized ArrayList object
        foreach (string s in people) {
            
            System.Console.WriteLine(s);
        }
    }   
}

You can use a SoapFormatter class in exactly the same way as shown in the BinarySerializationExample class; all you need to do is replace each instance of BinaryFormatter with SoapFormatter and change the using directives to import the System.Runtime.Serialization.Formatters.Soap namespace. You must also include a reference to the System.Runtime.Serialization.Formatters.Soap.dll assembly when you compile the code. The file SoapSerializationExample.cs in the sample code for this chapter contains an example of how to use the SoapFormatter class.

To illustrate the different results achieved using the BinaryFormatter and SoapFormatter classes, Figure 2.1 shows the contents of the people.bin file generated using the BinaryFormatter class, whereas Figure 2.2 shows the contents of the people.xml file generated using the SoapFormatter class.

click to expand
Figure 2.1: Contents of the people.bin file.

click to expand
Figure 2.2: Contents of the people.xml file.