How to pass an object to a common return type when the return type is a common interface?

I have a surprisingly ugly method that needs to pull various data from a database and use it to build an object of the requested type. The goal is to pull diverse ugliness into one place, so that classes that come from a class containing this method can be relatively clean.

I have no problem with when it should return a single object, even if the type is null:

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 where 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 cannot return rVal because it is an object, not an instance of T. But my changeType () function does not work with an error:

System.InvalidCastException: The object must implement IConvertible.

So, I have a generic method for which the return type is IList, and I have an object that is List, but my reference to it is of type Object. How to do this so that I can return it from a function?

+5
source share
1 answer

Your line return (T)Convert.ChangeType(value, t); does not work because your value object does not implement IConvertible .

From MSDN Docs

[...] For successful conversion, the value must implement the IConvertible interface, because the method simply terminates the call to the corresponding IConvertible method. This method requires support for converting a value to a conversion type.

To fix this, I am not sure about the general way, but for a specific case of value of type IEnumerable or IEnumerable<> , then you can try to execute then execute value.Select(x => changeType<ListGenT>(x)) linq request. Using the changeType method changeType , it should also handle nested generic types.

+1
source

Source: https://habr.com/ru/post/1239525/


All Articles