Je suis en train de mettre en place une sorte de désérialisation et je me débattais avec un problème suivant:
J'ai List<object>
et System.Reflection.Field
, c'est FieldType
peut être List<string>
, List<int>
ou List<bool>
, donc je dois convertir de List<object>
à ce type.
public static object ConvertList(List<object> value, Type type)
{
//type may be List<int>, List<bool>, List<string>
}
Je peux écrire chaque cas séparément, mais il devrait y avoir un meilleur moyen d’utiliser la réflexion.
Je crois que ce que tu veux c'est:
public static object ConvertList(List<object> value, Type type)
{
var containedType = type.GenericTypeArguments.First();
return value.Select(item => Convert.ChangeType(item, containedType)).ToList();
}
Exemple d'utilisation:
var objects = new List<Object> { 1, 2, 3, 4 };
ConvertList(objects, typeof(List<int>)).Dump();
Je ne suis pas sûr que cela soit utile ... Cela met en évidence la méthode extrêmement utile Convert.ChangeType, je suppose!
Mise à jour: Etant donné que d’autres ont bien fait remarquer que cela ne renvoie pas réellement un List<T>
(où T est le type en question) et que, par conséquent, je ne répondrais pas complètement à la question posée, j’ai choisi de fournir davantage. réponse à jour:
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 });
}
Si vous n'avez pas besoin de la conversion (le type de chaque valeur est donc correct et que vous n'avez pas d'ints dans les chaînes, etc.), supprimez l'indicateur performConversion
et le bloc associé.
Exemple: https://dotnetfiddle.net/nSFq22
Le type n'est connu qu'au moment de l'exécution, donc je suppose que la méthode générique n'est pas la solution
public static object ConvertList(List<object> value, Type type)
{
IList list = (IList)Activator.CreateInstance(type);
foreach (var item in value)
{
list.Add(item);
}
return list;
}
Vous ne savez pas si cela vous aidera, mais pouvez-vous utiliser Linq Cast?
List<object> theList = new List<object>(){ 1, 2, 3};
List<int> listAsInt = theList.Cast<int>();
Essaye ça:
public static List<T> ConvertList<T>(List<object> list)
{
List<T> castedList = list.Select(x => (T)x);
return castedList;
}
Appel:
List<object> myList = new List<object> {"test", "foo", "bar"};
List<string> stringList = ConvertList<string>(myList);
/// <summary>
/// Converts list of items into typed list of item of new type
/// </summary>
/// <example><code>
/// Consider source to be List<object>, newItemType is typeof(string), so resulting list wil have type List<string>
/// </code></example>
/// <param name="newItemType">New item type</param>
/// <param name="source">List of objects</param>
/// <returns>Typed List object</returns>
public static IList ConvertList(Type newItemType, IList source)
{
var listType = typeof(List<>);
Type[] typeArgs = { newItemType };
var genericListType = listType.MakeGenericType(typeArgs);
var typedList = (IList)Activator.CreateInstance(genericListType);
foreach (var item in source)
{
typedList.Add(item);
}
return typedList;
}
public static object ConvertList<T>(List<object> value) where T : class
{
var newlist = value.Cast<T>().ToList();
return newlist;
}
ou
public static List<T> ConvertList<T>(List<object> value) where T : class
{
List<T> newlist = value.Cast<T>().ToList();
return newlist;
}
public static List<T> ConvertType<T>(List<object> list) {
var list2 = new List<T>();
for(int i=0;i<list.Count;i++) list2.Add((T)list[i]);
return list2;
}