Monday, March 14, 2011

Generics

Problem:
I wrote a program that store the student and course information in Dictionary. Both Course and Student uses the same methods to store or retrieve record, so there is a duplication of code here, how can I make this code more efficient?

Impact:
Code duplication

Solution:
In situation like this where we have we two object doing the same thing, generic comes to rescue. Generics allow us to define type-safe data structures, without committing to actual data types. Generics allow us to reuse the same code algorithms without writing type specific duplicate code.Generics allow us to define type-safe classes without compromising type safety, performance, or productivity. 
Here is the application that I was working on.


In this application I have Main form that let you Add new student record, search student, Add course and search course. Both student forms and course forms uses the same ServiceFactory class to add the record and display record.


                                                                         Main Form
when user click on Add New Student button it display another form that  is used to collect student information. This form contains one button "Save" and when user click on save button it class the StudentService class. Here is the detail of the application. First Main form.

namespace RegistrationSystem.App
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private void btnAddRecord_Click(object sender, EventArgs e)
        {
            frmStudent frm = new frmStudent();
            frm.ShowDialog();
        }

        private void btnViewRecord_Click(object sender, EventArgs e)
        {
            frmDisplayStudent frm = new frmDisplayStudent();
            frm.ShowDialog();
        }

        private void AddCourseButton_Click(object sender, EventArgs e)
        {
            frmCourse frmCourse = new frmCourse();
            frmCourse.ShowDialog();
        }

        private void GetCourseButton_Click(object sender, EventArgs e)
        {
            frmDisplayCourse frmDisplayCourse = new frmDisplayCourse();
            frmDisplayCourse.ShowDialog();
        }
    }
}

now when user click on btnAddRecord, it displays student form.
user enter student record and click on Save button.


private void btnSave_Click(object sender, EventArgs e)
        {
            try
            {
                Student student = new Student();
                student.FirstName = txtFirstName.Text;
                student.LastName = txtLastName.Text;
                student.StudentId = txtStudentId.Text;

                StudentService.SaveStudent(student);
                MessageBox.Show("Record Saved Successfully");
                SetFormForNewRecord();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void SetFormForNewRecord()
        {
            txtFirstName.Text = "";
            txtLastName.Text = "";
            txtStudentId.Text = "";
        }

and here is the StudentService class.

public static class StudentService
    {
        public static void SaveStudent(Student student)
        {
            ServiceFactory<Student>.AddNewRecord(student.StudentId,student);
        }

        public static Student GetStudentById(string studentId)
        {
            return ServiceFactory<Student>.GetRecord(studentId);
        }
    }

StudentService uses ServiceFactory to save and get record. 

T is for type object.

public class ServiceFactory<T>
    {
        private static Dictionary<string, T> _data;

        static ServiceFactory()
        {
            _data = new Dictionary<string, T>();
        }

        public static void AddNewRecord(string Id,T record)
        {
            if(_data.ContainsKey(Id))
            {
                throw new Exception("Record already exist");
            }
            _data.Add(Id,record);
        }

        public static T GetRecord(string Id)
        {
            if (! _data.ContainsKey(Id))
            {
                throw new Exception("Record not found");
            }
            return _data[Id];
        }
    }

1 comment: