Перегрузки метода, которые отличаются только общим ограничением
Я столкнулся с некоторой проблемой, и я просто не могу найти хорошую работу.
Я хочу иметь эти 3 перегрузки:
public IList<T> GetList<T>(string query) where T: string
public IList<T> GetList<T>(string query) where T: SomeClass
public IList<T> GetList<T>(string query) where T: struct
Очевидно, что первое ограничение даже не будет компилироваться, так что моя первая проблема. (Я понимаю, я мог бы просто сделать это IList, но я хочу, чтобы тот же синтаксис для трех)
В любом случае причина для всего этого заключается в том, что эти методы являются частью оболочки для выполнения SQL-запросов к базе данных - я хочу иметь возможность возвращать результат в виде списка строк (в случае, если кто-то выбирает столбец varchar) список значений (int, float, whatever) или список классов (эти классы представляют таблицы и, следовательно, содержат несколько столбцов)
Я надеюсь, что эта часть была несколько понятной: -)
В любом случае моя большая проблема заключается в том, что я не могу сделать эти перегрузки, поскольку они используют одно и то же имя и список параметров.
Кроме того, я не могу объединить их в один и тот же метод, так как мне нужно вызвать метод в SomeClass в этой реализации, поэтому, если я не хочу делать какое-то тяжелое типизирование или, что еще хуже, отражение, мне нужно это ограничение.
Я понимаю, что то, что я пытаюсь сделать, невозможно, поэтому я ищу подходящий подход, который будет имитировать мои намерения.
Если некоторые из них немного неясны, не стесняйтесь спрашивать: -)
Edit:
Вот мой текущий код для версии "где T: SomeClass". Я пытаюсь добавить поддержку string/valuetypes к этому текущему коду, поэтому, возможно, мой первоначальный подход просто неверен - любые идеи приветствуются в основном: -)
public IList<TValue> GetList<TValue>(string query) where TValue : DbTable, new()
{
DataSet dataSet = GetDataSet(query);
IList<TValue> result = new List<TValue>();
if (dataSet.Tables.Count > 0)
{
foreach (DataRow row in dataSet.Tables[0].Rows)
{
TValue col = new TValue();
col.Fill(row);
result.Add(col);
}
}
return result;
}
Как вы можете видеть, мне нужен точный тип DbTable, чтобы создать новый конструктор.
Fill - абстрактный метод DbTable (который является абстрактным классом).
Ответы
Ответ 1
Как вы заметили; для этого нет хороших вариантов. Вы можете рассматривать разные имена (а не перегрузки) - GetStringList
и т.д.
Однако, интересно, было бы проще удалить ограничение. Единственная проверка типа с "как" - это не совсем "тяжелый" тип-литье, и это может сэкономить много боли.
Ответ 2
как насчет этого?
public IList<T> GetList<T>(string query) where T : new()
{
// whatever you need to distinguish, this is a guess:
if (typeof(T).IsPrimitiveValue)
{
GetPrimitiveList<T>(query);
}
else if (typeof(T) == typeof(string))
{
GetStringList<T>(query);
}
else
{
GetEntityList<T>(query);
}
}
private IList<T> GetStringList<T>(string query)
private IList<T> GetPrimitiveList<T>(string query)
private IList<T> GetEntityList<T>(string query)