General loading of a collection from a generic type

I have the following code where I am trying to create a generic collection for objects in my DAL (just an exercise, not production code). My problem is that I want to use the type passed in the Read method (which is part of the interface implemented by the classes).

I can't create new T

, so I don't have an instance of the object to work with, and I can't declare it as a base type, since I need a read method specified by a child of the base object.

Is this possible or am I barking on the wrong tree?

public class ItemDictionary<T> where T : ILoadable, DataItem
{

    public void Load()
    {
        using (IDataReader reader = SqlHelper.ExecuteReader(_connection, CommandType.StoredProcedure, _proc)) {
            Read(reader);
        }
    }

    bool Read(IDataReader reader)
    {
        while (reader.Read) 
        {
            T item = default(T);            //Here be the problem

            if (item.Read(reader)) 
            {
                this.Add(item.Guid, item);
            }
        }

        return true;
    }

}

public class ExampleObject : DataItem, ILoadable
{

    bool Read(IDataReader reader)
    {
        _var1 = reader.getString(0);
        _var2 = reader.getString(1);
        _var3 = reader.getString(2);

        return true;
    }
}

      

+1


a source to share


2 answers


You don't have a default constructor for the type (s) stored in the collection, and add the new () directive to the T directive:

public class ItemDictionary<T> where T : ILoadable, DataItem, new()

      



and then: -

    T item = new T();

      

+3


a source


It's not clear to me why you can't use new T()

(with a corresponding restriction on T

). It is also not clear to me why you are using an explicit interface implementation, and why your ILoadable

interface has a method called ILoadable

, mind you.

Is the problem that you can't always guarantee that there is a parameterless constructor in the object type? In this case, you will certainly need to create instances T

. Perhaps you really need to decouple T

from its factory, perhaps with a different interface:



public interface IFactory<T>
{
    // Roughly matching your current API
    bool TryRead(IDataReader reader, out T);

    // Simpler if you can just throw an exception on error
    T Read(IDataReader reader);
}

      

Then you can just pass the implementation IFactory<T>

to your constructor ItemDictionary<T>

.

+1


a source







All Articles