web-dev-qa-db-ja.com

List <object>をList <Type>に変換します。タイプは実行時に既知です

私はある種の逆シリアル化を実装していて、次の問題に苦労しています:

私はList<object>System.Reflection.Fieldを持っています。FieldTypeList<string>List<int>、またはList<bool>のいずれかなので、List<object>からその型に変換する必要があります。

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

私はそれぞれのケースを別々に書くことができますが、リフレクションを使用するより良い方法があるはずです。

17
Rustam Ganeyev

私はあなたが望むものは次のとおりだと信じています:

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

使用例:

var objects = new List<Object> { 1, 2, 3, 4 };

ConvertList(objects, typeof(List<int>)).Dump();

ただし、これがどれほど便利かはわかりません...非常に便利なConvert.ChangeTypeメソッドを強調しています。


Update:他の人はこれが実際にはList<T>(Tは問題の型)を返さないことを正しく指摘しているため、目の前の質問に完全に答えることはできないかもしれませんが、私はより最新の答えを提供することを選択しました:

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 });
}

変換が不要な場合(各値のタイプが実際に正しく、文字列に整数がない場合など)、performConversionフラグと関連するブロックを削除します。


例: https://dotnetfiddle.net/nSFq22

15
Richiban

タイプは実行時にのみ知られるので、私はジェネリックメソッドは行く方法ではないと思います

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

これがまったく役立つかどうかはわかりませんが、Linq Castを使用できますか?

List<object> theList = new List<object>(){ 1, 2, 3};
List<int> listAsInt = theList.Cast<int>();
7
DLeh
 public static object ConvertList<T>(List<object> value) where T : class
    {
        var newlist = value.Cast<T>().ToList();
        return newlist;
    }

または

  public static List<T> ConvertList<T>(List<object> value) where T : class
    {
        List<T> newlist = value.Cast<T>().ToList();
        return newlist;
    }
2
Maximc

これを試して:

public static List<T> ConvertList<T>(List<object> list)
{
    List<T> castedList = list.Select(x => (T)x);
    return castedList;
}

コール:

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
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