Загрузка общей коллекции из универсального типа - PullRequest
1 голос
/ 12 мая 2009

У меня есть следующий код, где я пытаюсь создать универсальную коллекцию для объектов в моем DAL (просто упражнение, а не рабочий код). Моя проблема в том, что я хочу использовать тип, переданный в метод Read (который является частью интерфейса, который реализуют классы).

Я не могу создать new T, поэтому у меня нет экземпляра объекта для работы, и я не могу объявить его как базовый тип, так как мне нужен метод read, указанный дочерним объектом базового объекта. *

Это действительно возможно, или я лаю не на том дереве?

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;
    }
}

Ответы [ 2 ]

3 голосов
/ 12 мая 2009

Не можете ли вы иметь конструктор по умолчанию для типов, содержащихся в коллекции, и добавить директиву new () в директиву where T:?

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

и затем: -

    T item = new T();
1 голос
/ 12 мая 2009

Мне не понятно , почему нельзя использовать new T() (с соответствующим ограничением на T). Мне также не ясно, почему вы используете явную реализацию интерфейса, и почему ваш ILoadable интерфейс имеет метод, называемый ILoadable, обратите внимание.

Является ли проблемой то, что вы не всегда можете гарантировать наличие конструктора без параметров в типе объекта? Если это так, вам, безусловно, понадобится что-то для создания экземпляров T. Возможно, вам действительно нужно отделить T от его фабрики, возможно, с другим интерфейсом:

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);
}

Тогда вы можете просто передать реализацию IFactory<T> в конструктор ItemDictionary<T>.

...