SYSK 264: Restricting Item Types in Generic Collections


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];


 


 

Comments (0)