У меня есть некоторые вызовы кода уровня доступа к данным сохраненный proc, и возвращает скалярные значения различных типов данных. Синтаксисом является ExecuteDecimal, ExecuteString, и т.д. Я хочу, чтобы это было Execute<string>
или Execute<decimal>
Я пробую эту реализацию, и я не могу скомпилировать, если я не делаю кастинг с помощью" (T) значение", если я пытаюсь проверить тип и назвать метод, чтобы сделать кастинг, никакую такую удачу.
ОБНОВЛЕННЫЙ вопрос, Почему я должен преобразовать в объект прежде, чем преобразовать в T?
ОБНОВЛЕННЫЙ код
internal T Execute<T>(string storedProcName, Hashtable parameters)
{
//Next lines do compile (thanks to suggestions from answers!)
if (typeof(T) == typeof(string))
return (T) (object) ExecuteScalar(storedProcName, parameters).ToString();
else if (typeof(T) == typeof(int))
return (T)(object) Convert.ToInt32(ExecuteScalar(storedProcName, parameters));
//Next line compiles, but not all things boxed in an object can
//be converted straight to type T (esp db return values that might contain DbNull.Value, etc)
return (T)ExecuteScalar(storedProcName, parameters);
}
Попробуйте следующее:
var result = ExecuteScalar(storedProcName, parameters);
if(Convert.IsDBNull(result))
return default(T);
if(result is T) // just unbox
return (T)result;
else // convert
return (T)Convert.ChangeType(result, typeof(T));
Обновлено : исправлена обработка DBNull
Возможно, вместо этого ваша функция могла бы быть изменена, чтобы разрешить передачу функции преобразования объекта:
internal T Execute<T>(string storedProcName, Hashtable parameters, Func<object, T> resultConverter)
{
}
Затем вы можете создать перегрузки для тех, о которых вы знаете:
internal string ExecuteForString(string storedProcName, Hashtable parameters)
{
return Execute(storedProcName, parameters, (o) => o.ToString());
}
internal int ExecuteForInt(string storedProcName, Hashtable parameters)
{
return Execute(storedProcName, parameters, Convert.ToInt32);
}
В в случае ваших проверок DBNull вы можете либо вернуть default (T)
, либо добавить другую перегрузку для передачи значения по умолчанию, если возвращается DBNull - например, в случае int может быть лучше вернуть -1 вместо 0.
typeof(T) == typeof(string)
и для проверки нулевого значения по DBNull.Value
общий метод:
internal T Execute<T>(string storedProcName, Hashtable parameters)
{
object res = ExecuteScalar(storedProcName, parameters);
if (Convert.IsDBNull(res))
return default(T); //or handle somehow
return (T)Convert.ChangeType(res, typeof(T));
}
попробуйте ключевое слово 'as'
object o = ExecuteScalar(storedProcName, parameters);
string s;
int i;
// .. more
if ((s = o as string) != null)
{
return s;
}
if ((i = o as int?) != null) // can't use as for value types, so use nullable
{
return Convert.ToInt32(o);
}
return o as T;