views:

150

answers:

4

Hi,

I want to create maintainable code, but this inheritance situation is causing me problems.

The issue is with my 2nd database helper class named InitUserExtension.

Since UserExtension inherits from User, I have to make sure that I mirror any changes in my InitUser helper to InitUserExtension.

I really don't like this as its prone to bugs, what's the solution?

My class definitions:

public class User
{
    public string Name {get; set; }
    public string Age { get; set; }
}

public class UserExtension : User
{
    public string Lastname {get; set; }
        public string Password {get; set; }

}

My database helpers:

public static SqlDataReader InitUser(SqlDataReader dr)
{
      User user = new User();

      user.Name = Convert.ToString(dr["name"]);
      user.Age ...
}


public static SqlDataReader InitUserExtension(SqlDataReader dr)
{
      UserExtension user = new UserExtension();


      // note: mirror attributes from User
      user.Name = Convert.ToString(dr["name"]);
      user.Age ...



      user.Lastname = Convert.ToString(dr["lastname"]);
      user.Password = ....;
}
+1  A: 

Why don't you call InitUser from the InitUserExtension method. Let the base initialization handle the base class properties and let the extended initializer handled the extension class properties.

vfilby
+2  A: 

How about moving the processing of Name etc into a method (accepting either a User or a T : User), and call that from both?

private static void InitUser(User user, SqlDataReader dr)
{ // could also use an interface here, or generics with T : User
  user.Name = Convert.ToString(dr["name"]);
  user.Age ...
}


public static User InitUser(SqlDataReader dr)
{
    User user = new User();
    InitUser(user, dr);
    return user;
}

public static UserExtension InitUserExtension(SqlDataReader dr)
{
  UserExtension user = new UserExtension();
  InitUser(user, dr);
  user.Lastname = Convert.ToString(dr["lastname"]);
  user.Password = ....;
  return user;
}

As an alternative, you could reduce the line count, but increase the complexity, using generics:

private static T InitUserCore<T>(SqlDataReader dr) where T : User, new()
{
    T user = new T();
    // ...
    return user;
}
public static User InitUser(SqlDataReader dr)
{
    return InitUserCore<User>(dr);
}
public static UserExtension InitUserExtension(SqlDataReader dr)
{
    UserExtension user = InitUserCore<UserExtension>(dr);
    // ...
    return user;
}
Marc Gravell
I have a parseRow<T> method, then i can tell it what object i want it to create and assign values to (from a reader or tablerow)
Andrew Bullock
@Andrew Bullock - like the edit I've just added?
Marc Gravell
A: 

I'm not sure why you haven't placed the assignation code within the classes themselves, but it may have to do with how you're getting the information to store it...

My solution would be to rewrite it something like:

public class User
{
    public string Name {get; set; }
    public string Age { get; set; }

    public User(DataReader dr)
    {
       user.Name = Convert.ToString(dr["name"]);
       user.Age ...
    }
}

public class UserExtension : User
{
    public string Lastname {get; set; }
    public string Password {get; set; }

    public UserExtension(DataReader dr):base(dr)
    {
        user.Lastname = Convert.ToString(dr["lastname"]);
        user.Password = ....;

    }
}

Milage may vary due to your circumstances

This way, a call like

var MyExtension = new UserExtension(dr);

will populate all fields appropriately.

Wobin
Re mnixing db code in the classes: as a guess... persistance ignorance and separation of concerns - i.e. a POCO shouldn't have to know about the database details.
Marc Gravell
Hm, true. However, I can't see how he's passing back the users he's created in the database code. If he had the declaration outside the database functions and passed into it, he could chain the function calls as well, easily enough without issue.
Wobin
+1  A: 

If you do prefer helpers do the same with helpers

public class InitUser
{
 public InitUser(SqlDataReader dr, User u) { }
}

public class InitUserExtension : InitUser
{
 public InitUserExtension(SqlDataReader dr , UserExtension u) : base(dr, u) { }
}
Din