Polymorphic Instantiation

Polymorphic Instantiation

Old forum URL: forums.lhotka.net/forums/t/3146.aspx


Wile E. Coyote posted on Thursday, July 05, 2007

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

 

skagen00 replied on Thursday, July 05, 2007

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

 

triplea replied on Thursday, July 05, 2007

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?).

skagen00 replied on Thursday, July 05, 2007

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.

 

 

skagen00 replied on Thursday, July 05, 2007

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)

 

Wile E. Coyote replied on Friday, July 06, 2007

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?

ajj3085 replied on Friday, July 06, 2007

You'd need to create a PersonFactory class, which would likely be static.  Its get could return a Person instance. The factory would execute the dataportal, load the data, decide which concrete type to create and create it, passing it the data it needs to load.

If you need one of the subclasses, you'll have to create static factory methods on the subclass, but you would need to know what kind of person you expect to create in advance.

Does that make sense?

Andy

Copyright (c) Marimer LLC