Как привести объект к универсальному возвращаемому типу, если возвращаемый тип является универсальным интерфейсом?
У меня есть поразительно уродливый метод, который должен извлекать разные данные из базы данных и использовать его для создания объекта запрошенного типа. Цель состоит в том, чтобы вытащить сортированное уродство в одно место, чтобы классы, происходящие от класса, содержащего этот метод, могли быть относительно чистыми.
У меня нет проблем с тем, когда он должен возвращать один объект, даже когда тип обнуляется:
protected T getValue<T>(ParameterObject myParameterObject)
{
var typeOfT = typeof (T);
if (typeOfT == typeof(bool))
{
string val = this.getValue(myParameterObject);
if (val == null)
return default(T);
bool rVal;
if (!Boolean.TryParse(val, out rVal))
return default(T);
return changeType<T>(rVal);
}
if (typeOfT == typeof (double?))
{
string val = this.getValue(myParameterObject);
if (val == null)
return default(T);
double rVal;
if (!Double.TryParse(val, out rVal))
return default(T);
return changeType<T>(rVal);
}
[...]
}
public static T changeType<T>(object value)
{
var t = typeof(T);
if (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(Nullable<>))
return (T)Convert.ChangeType(value, t);
if (value == null)
return default(T);
t = Nullable.GetUnderlyingType(t);
return (T)Convert.ChangeType(value, t);
}
К сожалению, у меня есть случаи, когда мой желаемый тип возврата - IList, где я хочу вернуть список:
protected T getValue<T>(ParameterObject myParameterObject)
{
var typeOfT = typeof (T);
if (typeOfT.IsGenericType)
{
if (typeOfT.GetGenericTypeDefinition() == typeof (IList<>))
{
var genericArgumentType = typeOfT.GenericTypeArguments.FirstOrDefault();
var baseType = typeof (List<>);
var genericType = baseType.MakeGenericType(new[] {genericArgumentType});
var rVal = Activator.CreateInstance(genericType);
[code to populate the list]
return changeType<T>(rVal);
}
[...]
}
Я не могу вернуть rVal, потому что это объект, а не экземпляр T. Но моя функция changeType() завершается с ошибкой:
System.InvalidCastException: объект должен реализовывать IConvertible.
Итак, у меня есть универсальный метод, для которого тип возвращаемого значения - IList, и у меня есть объект, который является списком, но моя ссылка на него имеет тип Object. Как я могу привести его, чтобы я мог вернуть его из функции?
1 ответ
Ваш return (T)Convert.ChangeType(value, t);
линия терпит неудачу, потому что ваш value
объект не реализует IConvertible
,
[...] Чтобы преобразование прошло успешно, значение должно реализовывать интерфейс IConvertible, поскольку метод просто переносит вызов соответствующего метода IConvertible. Для этого метода требуется, чтобы преобразование значения в ConversionType поддерживалось.
Чтобы это исправить, я не уверен в общем, но для конкретного случая value
существо IEnumerable
или же IEnumerable<>
типа, тогда вы можете попытаться разыграть, затем выполнить value.Select(x => changeType<ListGenT>(x))
запрос linq. Используя ваш changeType
метод рекурсивно, это должно обрабатывать и вложенные универсальные типы.