Say, you have implemented the following data class called Message in a YourCompany.DataContracts.Shared assembly (code below). 

When creating a collection of messages class, some may choose to implement it similar to the code below:

[DataContract(Namespace = ""), Serializable]

public class MessageCollection : System.Collections.Generic.SortedDictionary<DateTime, Message>

{

}

 

 

The problem with this approach is that if you created a class that derives from the Message class, let’s call it MessageEx, and you want a collection of the MessageEx classes, you’ll either have to create a new collection class (e.g. MessageExCollection), or you’ll end up writing a lot of code casting the collection items to the MessageEx type.

 

A better, in my opinion, choice is to create a generic collection, and restrict the type of items that are allowed to be inserted into such collection.  Here is what I mean:

 

#region MessageCollection

    [DataContract(Namespace = ""), Serializable]

    public class MessageCollection<T> : System.Collections.Generic.SortedDictionary<DateTime, T> where T : Message

    {

        public void Add(T item)

        {

            base.Add(item.CreatedOn, item);

        }

 

        public T this[long recordID]

        {

            get

            {

                T result = default(T);

 

                foreach (T item in base.Values)

                {

                    if (item.RecordID == recordID)

                    {

                        result = item;

                        break;

                    }

                }

 

                return result;

            }

        }

 

// TODO: add other methods/properties

//      (e.g. get by instance id, get by index, etc)

    }

#endregion

 

 

Now, you can have a Message class and MessageEx class, and instanced of both classes can be inserted into MessageCollection.  And yes, no casting required when inserting or retrieving and using the message item!

 

 

[DataContract(Namespace = ""), Serializable]

public class MessageEx : YourCompany.DataContracts.Shared.Message

{

    private string _someOtherData;

 

    [DataMember]

    public string SomeOtherData

    {

        get { return _someOtherData; }

        set { _someOtherData = value; }

    }   

}

 

 

namespace YourCompany.DataContracts.Shared

{

    #region Message

    [DataContract(Namespace = ""), Serializable]

    public class Message

    {

        private string _instanceID = Guid.NewGuid().ToString();

        private long _recordID;

        private string _text;

        private DateTime _createdOn;

        private string _createdBy;

 

        public Message()

        {

        }

 

        public Message(long recordId, string text, DateTime createdOn, string createdBy)

        {

            _recordID = recordId;

            _text = text;

            _createdOn = createdOn;

            _createdBy = createdBy;

        }

 

        [DataMember]

        public string InstanceID

        {

            get { return _instanceID; }

            set { _instanceID = value; }

        }

 

        [DataMember]

        public long RecordID

        {

            get { return _recordID; }

            set { _recordID = value; }

        }

 

        [DataMember]

        public string Text

        {

            get { return _text; }

            set { _text = value; }

        }

 

        [DataMember]

        public DateTime CreatedOn

        {

            get { return _createdOn; }

            set { _createdOn = value; }

        }

 

        [DataMember]

        public string CreatedBy

        {

            get { return _createdBy; }

            set { _createdBy = value; }

        }

    }

    #endregion

 

 

 

    [DataContract(Namespace = ""), Serializable]

    public class MessageEx : YourCompany.DataContracts.Shared.Message

    {

        private string _someOtherData;

 

        [DataMember]

        public string SomeOtherData

        {

            get { return _someOtherData; }

            set { _someOtherData = value; }

        }

    }

 

 

 

Usage:

 

MessageCollection<MessageEx> messages =

new MessageCollection<MessageEx>();

 

. . .


// No casting required :)

MessageEx message = messages[recordID];