Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

C# Inheritance Design Question 1

Status
Not open for further replies.

spangeman

Programmer
Oct 16, 2004
96
0
0
EU
Hi All

Complete newby question.

I have some objects I want to generate and make available through a method that can be called to return them in a dictionary collection. There are a few different objects but they share some properties and methods so I thought this would be a good time to use inheritance. But this is all new to me so I think I am designing this incorrectly. There is a table in a database which decides which objects need to be generated and also holds some of their properties.

I have simplified the code to make this posting easier.

Classes for the objects
public class ExampleBaseClass
{
//common properties
public string objectName;
public string prop1;
public string prop2;
public string prop3;
}

public class ExampleInheritClass1 : ExampleBaseClass
{
//addiotnal properties
public string extraprop1;
public string extraprop2;
//More object specific methods and properties go here
}

public class ExampleInheritClass2 : ExampleBaseClass
{
//addiotnal properties
public string another_extraprop1;
public string another_extraprop2;
//More object specific methods and properties go here
}


Class to retrieve them
public class myClassToGetObjects
{

public Dictionary<string, ExampleBaseClass> dictmyObjects = new Dictionary<string, ExampleBaseClass>();
private DataTable dataTableOfObjects = new DataTable();

public myClassTogetObjects(string objectName)
{
getObjectsDataFromDatabase();

foreach (DataRow row in dataTableOfObjects.Rows)
{
if (row["objectName"].ToString() == objectName)
{
populateObjectDict(row);
}
}
}

private void getObjectDataFromDatabase()
{

SqlConnection myConnection = new SqlConnection("server=test;" + "Trusted_Connection=yes;" + "database=testDB; " + "connection timeout=30");
SqlDataAdapter myAdapter = new SqlDataAdapter("SELECT * MY_TABLE_OF_OBJECTS", myConnection);
myAdapter.Fill(dataTableOfObjects);
myConnection.Close();
myConnection = null;

}

private void populateObjectDict(DataRow objDataRow)
{
ExampleBaseClass MyObject = new ExampleBaseClass();

MyObject.objectName = objDataRow["objectName"].ToString();
MyObject.prop1 = objDataRow["prop1"].ToString();
MyObject.prop2 = objDataRow["prop2"].ToString();
MyObject.prop3 = objDataRow["prop3"].ToString();

switch (objDataRow["ObjectType"].ToString())
{
case "Example1":
//set object specific properties
break;

case "Example2":
//set object specific properties
break;

dictmyObjects.Add(MyObject.objectName, MyObject);
}
}
}


I am stuck with the last method, populating the dictionary with my objects.

I want to have one MyObject which is set to the correct type based on the ObjectType from the database and then add this to the dictionary as I loop through. But I can't see to do this as MyObject will only ever have the properties of the base class. How do I turn it into one of the derived classes as I loop through? Or am I going about this in the wrong way?

 
To create the subclasses i would create a factory object for each subclass. it would look something like this
Code:
interface Factory
{
   bool CanHydrate(IDataRecord record);
   BaseEntity Hydrate(IDataRecord record);
}

class ThisEntityFactory : Factory
{
   public bool CanHydrate(IDataRecord record)
   {
      return record["ObjectType"] == "this";
   }

   public BaseEntity Hydrate(IDataRecord record)
   {
       return new ThisEntity {
                PropertyA = record[".."],
                PropertyB = record[".."],
                Property1 = record[".."],
           }
   }
}

class ThatEntityFactory : Factory
{
   public bool CanHydrate(IDataRecord record)
   {
      return record["ObjectType"] == "that";
   }

   public BaseEntity Hydrate(IDataRecord record)
   {
       return new ThatEntity {
                PropertyA = record[".."],
                PropertyB = record[".."],
                Property2 = record[".."],
           }
   }
}

class BaseEntityRepository
{
   private readonly IEnumerable<Factory> factories;

   public BaseEntityRepository(params Factory[] factories)
   {
     this.factories = factories;
   }

   public BaseEntityRepository()
      : this(new ThisEntityFactory(), new ThatEntityFactory())
   {
   }

   public IEnumerable<BaseEntity> GetAll()
   {
      using(var command = connection.CreateCommand())
      {
          ..configure command
          using(var reader = command.ExecuteReader())
          {
              while(reader.Read)
              {
                 foreach(var factory in factories)
                 {
                     if(factory.CanHydrate(reader) == false) continue;
                     yield return factory.Hydrate(reader);
                 }
              }
          }
      }
   }
}
if you introduce new entity type create a new factory class and add to the list of factories on the repository object.

when consuming the enumeration of base entities you will probably run into problems of Liskov Substitution Principle. (1 of the 5 overarching design principles S.O.L.I.D.)

There are various ways to solve that problem. 1 may be to create a repository for each specific type
Code:
class ThisEntityRepository
{
   public IEnumerable<ThisEntity> GetAll()
   {
      var factory = new ThisFactory();
      using(var command = connection.CreateCommand())
      {
          ..configure command to only select "this"
          using(var reader = command.ExecuteReader())
          {
              while(reader.Read)
              {
                 yield return factory.Hydrate(reader);
              }
          }
      }
   }
}

class ThatEntityRepository
{
...
}
another option is a method on the base entity.
Code:
abstract class BaseEntity
{
   public string PropertyA {get;set;}
   public string PropertyB {get;set;}

   public abstract void DoSomething();
}

class ThisEntity : BaseEntity
{
   public int Property1 {get;set;}

   public overrdie void DoSomething()
   {
       ...
   }
}

class ThatEntity : BaseEntity
{
   public DateTime Property2 {get;set;}

   public overrdie void DoSomething()
   {
       ...
   }
}
I don't think any of this will answer your question 100%. but it should be enough to get you thinking about the structure of the code and how to compose/inherit objects.

Jason Meckley
Programmer

faq855-7190
faq732-7259
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top