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?
The Java compiler won't let you cast a generic type across its type parameters because the target type, in general, is neither a subtype nor a supertype.
So methods of generic or nongeneric classes can use generic types as argument and return types as well. Here are examples of those usages: // Not generic methods class GenericClass < T > { // method using generic class parameter type public void T cache ( T entry ) { ... } }
Yes, you can define a generic method in a non-generic class in Java.
Your return (T)Convert.ChangeType(value, t);
line is failing because your value
object does not implement IConvertible
.
From MSDN docs
[...] For the conversion to succeed, value must implement the IConvertible interface, because the method simply wraps a call to an appropriate IConvertible method. The method requires that conversion of value to conversionType be supported.
To fix this, I'm not sure of a general way but for the specific case of value
being of an IEnumerable
or IEnumerable<>
type, then you could try to cast then perform a value.Select(x => changeType<ListGenT>(x))
linq query. By using your changeType
method recursively this should handle nested generic types as well.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With