将List <object>转换为List <type>,Type在运行时已知</type> </object>

时间:2014-04-08 14:07:36

标签: c# system.reflection

我正在实施某种反序列化,并在下一个问题上挣扎:

我有List<object>System.Reflection.FieldFieldType可以是List<string>List<int>List<bool>,所以我需要转换自{ {1}}到那些类型。

List<object>

我可以单独编写每个案例,但应该有更好的方法使用反射。

8 个答案:

答案 0 :(得分:13)

我相信你想要的是:

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方法!


更新:由于其他人已经正确地指出这实际上没有返回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

答案 1 :(得分:10)

该类型仅在运行时已知,因此我认为通用方法不是最佳方法

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

答案 2 :(得分:4)

不确定这是否有帮助,但您可以使用Linq Cast吗?

List<object> theList = new List<object>(){ 1, 2, 3};
List<int> listAsInt = theList.Cast<int>();

答案 3 :(得分:1)

试试这个:

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

答案 4 :(得分:1)

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

答案 5 :(得分: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;
    }

答案 6 :(得分:0)

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

答案 7 :(得分:0)

这里有一个扩展方法,类似于 linq 扩展方法,不同之处在于它接受一个类型而不是类型参数的参数:

public static IList CastToList(this IEnumerable source, Type itemType)
{
    var listType = typeof(List<>).MakeGenericType(itemType);
    var list = (IList)Activator.CreateInstance(listType);
    foreach (var item in source) list.Add(item);
    return list;
}

用法:

var list = new List<object>();
list.add(1);
list.add(2);
var boxedIntList = list.CastToList(typeof(int)); //type is object{List<int>}