Hi,
How do you go about polymorphic instantiation using CSLA? Here's a simplified example:
Person (abstract base class), Student (first concrete child class) and Lecturer(second concrete child class). The concrete type is represented by a flag on the Person table as "S" or "L". How do I go about fetching a Person with name = "Joe Blogs" and instantiating the correct concrete instance (student or lecturer)? Let's assume that a Person can either a Student or a Lecturer and not both for simplicity purposes. The DataPortal_Fetch method instantiates an instance of a particular class based on the declaring type of the criteria object (in this case Person). How do I go about only instantiating the concrete type based on the flag "S" or "L".
Is there any simple and most importantly correct method to accomplish this in the framework?
Thanks for the help
Hello,
Because your Person is an abstract generic and doesn't really have responsibility to know of the subclasses, I would suggest a PersonFactory static class.
PersonFactory could have classes such as: Exists(string personName), GetPerson(string personName), GetPerson(int personId).
The return values on the GetPerson methods would be IPerson. IPerson should be an interface that exposes everything from your person class, and Person should thus implement IPerson.
By that nature, Student and Lecturer will implement IPerson. So when your factory does the retrieval in GetPerson, it should first just nab the flag, and then call the appropriate factory method on the concrete class.
Something like:
public static IPerson GetPerson(int personId)
{
if (Student.Exists(personId))
{
return Student.GetStudent(personId);
}
else if (Lecturer.Exists(personId))
{
return Lecturer.GetLecturer(personId);
}
else
{
//throw exception - not found
}
}
That's how I do it, and it works well.
Chris
I can see how this could work just fine but have a couple of questions/remarks. Wouldn't it be better to have a Person.Exists(int id) and then do the fetching within GetPerson(). Then depending on the person type field you call either Student.GetStudent(IPerson person) or Lecturer.GetLecturer(IPerson person)?
That would reduce the database hits but not sure if its a valid OO design. It would also remove the filtering logic from the database and place it within your class (although this might mean introducing database logic in your objects?).
PersonFactory shouldn't fetch each of the concrete classes - that is, have any knowledge on the internal fetching & population of the classes - any concrete class could have their own data requirements that would require a different fetching & population algorithm.
PersonFactory should simply facilitate requests in a generic manner and handle the delegation to the appropriate classes.
If you have common fetching components you would be able to introduce that in protected instance methods in the Person class which could be leveraged by the fetching logic for your student and lecturer classes.
BTW, if you meant having the factory methods right off of Person - that's not possible - because Person is likely a Generic Class for him/her. Can't invoke a static method on a generic class - like Person<T>.GetPerson() - no can do.
Person<T> : BusinessBase<Person>, IPerson where T : Person<T>
Lecturer : Person<Lecturer>
Student : Person<Student>
(At least that's what I suspect he has for his classes)
Thanks for the replies. It just the a bit "clunky" for want of a better word. What I'd like to do is fetch the single result set from the database and based on the flag field instantiate the concrete instance.
Is there no simple way to do this in the framework?
Copyright (c) Marimer LLC