Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert List<object> to List<Type>, Type is known at runtime

Tags:

I am implementing some kind of deserialization and struggled with a next problem:

I have List<object> and System.Reflection.Field, it's FieldType can be List<string>, List<int> or List<bool>, so I need to convert from List<object> to that types.

public static object ConvertList(List<object> value, Type type) {    //type may be List<int>, List<bool>, List<string> } 

I can write each case separately, but there should be a better way using reflection.

like image 566
Rustam Ganeyev Avatar asked Apr 08 '14 14:04

Rustam Ganeyev


People also ask

Can we convert List string to list object?

Pass the List<String> as a parameter to the constructor of a new ArrayList<Object> . List<Object> objectList = new ArrayList<Object>(stringList); Any Collection can be passed as an argument to the constructor as long as its type extends the type of the ArrayList , as String extends Object .

Can we convert object to List?

//Assuming that your object is a valid List object, you can use: Collections. singletonList(object) -- Returns an immutable list containing only the specified object. //Similarly, you can change the method in the map to convert to the datatype you need.


1 Answers

I believe what you want is:

public static object ConvertList(List<object> value, Type type) {     var containedType = type.GenericTypeArguments.First();     return value.Select(item => Convert.ChangeType(item, containedType)).ToList(); } 

Example usage:

var objects = new List<Object> { 1, 2, 3, 4 };  ConvertList(objects, typeof(List<int>)).Dump(); 

I'm not sure how useful this is though... It highlights the insanely useful Convert.ChangeType method I guess!


Update: Since others have correctly pointed out that this doesn't actually return a List<T> (where T is the type in question) and therefore might not fully answer the question at hand, I have chosen to provide a more up to date answer:

public static object ConvertList(List<object> items, Type type, bool performConversion = false) {     var containedType = type.GenericTypeArguments.First();     var enumerableType = typeof(System.Linq.Enumerable);     var castMethod = enumerableType.GetMethod(nameof(System.Linq.Enumerable.Cast)).MakeGenericMethod(containedType);     var toListMethod = enumerableType.GetMethod(nameof(System.Linq.Enumerable.ToList)).MakeGenericMethod(containedType);      IEnumerable<object> itemsToCast;      if(performConversion)     {         itemsToCast = items.Select(item => Convert.ChangeType(item, containedType));     }     else      {         itemsToCast = items;     }      var castedItems = castMethod.Invoke(null, new[] { itemsToCast });      return toListMethod.Invoke(null, new[] { castedItems }); } 

If you don't need the conversion (so the type of each value is actually correct, and you don't have ints in strings etc), then remove the performConversion flag and the associated block.


Example: https://dotnetfiddle.net/nSFq22

like image 133
Richiban Avatar answered Sep 21 '22 19:09

Richiban