1

I have a class that loads data from my database. In this class, I have a function that actually loads the data and returns it to the calling function in the form of a DataTable.

I then iterate through the DataTable and create object of various classes based on each row.

What I would like to do, is change the flow so I can call the function that loads the data in a way that it can determine the type of object that should be created. Here are 2 psuedo calls to show the type of call I would like to make:

List<Teacher> =this.loadData(String sql, Hashtable data, {teachers class});
List<Student> = this.loadData(String sql, Hashtable data, {students class});

Right now the classes Teacher and Student don't extend a common class. However, if it helps, I can make a change like that.

lee

UPDATE:

Thanks to everyone who has given answers so far. It seems none of the solutions would actually improve the code I have or are beyond my programming skills.

I did find this post: Create an instance of a class from a string

In there someone mentions the following technique for creating a class from a string: System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(string className)

However, they also say that the resulting object has to be cast into the actual class. So it makes me wonder if I put the resulting class(before casting) into a List, will doing so automatically cast the object?

Community
  • 1
  • 1
Lee Loftiss
  • 3,035
  • 7
  • 45
  • 73

4 Answers4

2

Try wrapping your code that retrieves your database data into a class if you haven't. Then add two methods to return the specific type of object.

public class MyDataProvider
{
    bool isDataLoaded = false;

    public void LoadData(String sql, Hashtable data)
    {
        // Load data.
        isDataLoaded = true; // Or whatever mechanism you want to use to ensure data is loaded.
    }

    public IEnumerable<Student> GetStudents()
    {
        // Process student data if isDataLoaded.    
    }

    public IEnumerable<Teacher> GetTeachers()
    {
        // Process teacher data if isDataLoaded.
    }
}

And then use your Lists as you described.

MyDataProvider dp = new MyDataProvider("abc", data);

List<Student> students = new List<Student>();
students.AddRange(dp.GetStudents());

List<Teacher> teachers = new List<Teacher>();
teachers.AddRange(dp.GetTeachers());

Of course this is just one approach, but I think it will keep things a bit cleaner than what you described. You could also use generics, but you would need to provide a common interface for the Student and Teacher.

Inisheer
  • 20,376
  • 9
  • 50
  • 82
2

Not that I'd recommend it, but to strictly answer the question, you could do the following:

public List<T> loadData<T>(String sql, Hashtable data)
{
    var type = typeof(T);

    if (type == typeof(Teacher))
    {
        // replace with code that builds Teacher list...
        return List<Teacher>() as List<T>;
    }
    else if (type == typeof(Student))
    {
        // replace with code that builds Student list...
        return List<Student>() as List<T>;
    }
    else
    {
        throw new NotImplementedException();
    }
}

To call it, do the following:

var teachers = loadData<Teacher>(sqlString, dataTable);
var students = loadData<Student>(sqlString, dataTable);

Of course, this approach has maintenance issues as the number of types grow. There may be other approaches, but the one suggested by @Inisheer is a solid one.

Matt Davis
  • 45,297
  • 16
  • 93
  • 124
0

You can use an enum to enumarate your classes and pass variable of this type to your function. But I think it is not good idea to have one function for loading all lists because if you have many classes to load you will end up with messy code.

user1429899
  • 288
  • 5
  • 15
0

It sounds like you want to write a simple ORM (Object Relational Mapping) component. Rather than implement it yourself, I would investigate Microsoft's Entity Framework or NHibernate. These will load and save objects from a database with as much fine-grained control over the serialization as you need.

However, focusing on the problem you have, I would recommend splitting out the data loading to a separate class for each object, effectively the repository pattern. That way, as classes are added or removed to your product, you are not focusing changes on a single class. The repository classes may share a common base class to avoid code duplication.

akton
  • 14,148
  • 3
  • 43
  • 47