I have an astoundingly ugly method that's supposed to pull assorted data from a database, and use it construct an object of a requested type. The goal is to pull the assorted ugliness into a single place, so that classes that derive from the class containing this method can be relatively clean.
I'm not having a problem with when it's supposed to return a single object, even when the type is nullable:
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);
}
Unfortunately, I have cases in which my desired return type is IList, where I want to return a List:
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);
}
[...]
}
I can't return an rVal, because it's an object, not an instance of T. But my changeType() function is failing, with an error:
System.InvalidCastException: Object must implement IConvertible.
So, I have a generic method for which the return type is IList, and I have an object which is a List, but my reference to it is of type Object. How do I cast it so that I can return it from the function?
Your
return (T)Convert.ChangeType(value, t);line is failing because yourvalueobject does not implementIConvertible.From MSDN docs
To fix this, I'm not sure of a general way but for the specific case of
valuebeing of anIEnumerableorIEnumerable<>type, then you could try to cast then perform avalue.Select(x => changeType<ListGenT>(x))linq query. By using yourchangeTypemethod recursively this should handle nested generic types as well.