web-dev-qa-db-fra.com

Convertir la liste <objet> en liste <Type>, le type est connu à l'exécution

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.

12
Rustam Ganeyev

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

11
Richiban

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;
}
10
Guillaume

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>();
2
DLeh

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);
1
    /// <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;
    }
1
Vladimir Roytman
 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;
    }
1
Maximc
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;
}
0
kevin