0

I have the following interface and class

public interface IOwner
{
    int Owner_pkid { get; set; }
    string Name { get; set; }
}

public class Owner : IOwner
{
    public Owner()
    {

    }

    public int Owner_pkid { get; set; }
    public string Name { get; set; }
}

I then have the following Data Access Methods in a separate class

    public List<IOwner> GetAllOwners()
    {
        var sql = "SELECT owner_pkid, name from dbo.Owners ";

        using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString))
        using (SqlCommand cmd = new SqlCommand(sql, conn))
        {
            cmd.CommandType = CommandType.Text;
            List<IOwner> owners = new List<IOwner>();
            conn.Open();

            using (SqlDataReader reader = cmd.ExecuteReader())
                BindResultSet<IOwner>(reader, owners);

            return owners;
        }
    }

    private void BindResultSet<T>(SqlDataReader reader, List<T> items) where T : new()
    {
        int counter = 0;

        if (!reader.IsClosed)
        {
            while (reader.Read())
            {
                T record = GetNextDataObject<T>(items, counter);
                counter++;
                BindRecord<T>(reader, record);
            }
        }
    }

    private T GetNextDataObject<T>(List<T> items, int pointer) where T : new()
    {
        if (pointer < items.Count)
        {
            return items[pointer];
        }
        else
        {
            items.Add(new T());
            return items[items.Count - 1];
        }
    }

    private void BindRecord<IOwner>(SqlDataReader reader, IOwner owner)
    {
        owner.Name = (string)reader["name"];
        owner.Owner_pkid = (int)reader["owner_pkid"];
    }

I am getting 2 separate errors with this code:

  1. In the GetAllOwners method I am getting an error with the call to BindResultSet which says

IOwner must be a non-abstract type with a parameterless constructor in order to be used here

I have a parameterless constrctor on the implementing class - don't think i can add one to the interface

  1. In the final BindRecord method I am getting an error whereby the two property names are not recognized. This is possibly as a result of the first issue
Sperick
  • 2,691
  • 6
  • 30
  • 55
  • Do you have multiple classes that inherits from the IOwner interface ? I assume that BindResultSet and GetNextDataObject can be used with multiple interface ? (IFoo, IBar, ...) – Thibault Aug 11 '19 at 12:43

1 Answers1

1

The problem is that you cannot do new on an interface. So "new T" where T is IOwner will not work.

There are a number of different ways to fix this. The cleanest approach would be to add a factory interface whose only purpose is to create IOwner objects, say IOwnerFactory. Instantiate the factory at the top level and pass it down to the methods that need to create objects.

So instead of item.Add(new T()) use item.Add(ownerFactory.Create())

AQuirky
  • 4,691
  • 2
  • 32
  • 51