C# 转换列表<;对象>;列出<;类型>;,类型在运行时是已知的

C# 转换列表<;对象>;列出<;类型>;,类型在运行时是已知的,c#,system.reflection,C#,System.reflection,我正在实施某种反序列化,并努力解决下一个问题: 我有List和System.Reflection.Field,它的FieldType可以是List,List或List,所以我需要从List转换成那种类型 public static object ConvertList(List<object> value, Type type) { //type may be List<int>, List<bool>, List<string> } 公共

我正在实施某种反序列化,并努力解决下一个问题:

我有
List
System.Reflection.Field
,它的
FieldType
可以是
List
List
List
,所以我需要从
List
转换成那种类型

public static object ConvertList(List<object> value, Type type)
{
   //type may be List<int>, List<bool>, List<string>
}
公共静态对象转换列表(列表值,类型)
{
//类型可以是列表、列表、列表
}
我可以分别编写每个案例,但应该有更好的方法使用反射。

试试这个:

public static List<T> ConvertList<T>(List<object> list)
{
    List<T> castedList = list.Select(x => (T)x);
    return castedList;
}
公共静态列表(列表列表)
{
List castedList=List.Select(x=>(T)x);
回归种姓名单;
}
电话:

List myList=新列表{“test”、“foo”、“bar”};
List stringList=ConvertList(myList);
公共静态列表类型(列表){
var list2=新列表();

对于(int i=0;i我不确定这是否有帮助,但您可以使用Linq Cast吗

List<object> theList = new List<object>(){ 1, 2, 3};
List<int> listAsInt = theList.Cast<int>().ToList();
List theList=newlist(){1,2,3};
List listAsInt=theList.Cast().ToList();
公共静态对象转换列表(列表值),其中T:class
{
var newlist=value.Cast().ToList();
返回newlist;
}

公共静态列表ConvertList(列表值),其中T:class
{
List newlist=value.Cast().ToList();
返回newlist;
}

只有在运行时才知道该类型,所以我猜泛型方法不是最好的选择

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;
}
公共静态对象转换列表(列表值,类型)
{
IList list=(IList)Activator.CreateInstance(类型);
foreach(价值中的var项目)
{
列表。添加(项目);
}
退货清单;
}

我相信您想要的是:

public static object ConvertList(List<object> value, Type type)
{
    var containedType = type.GenericTypeArguments.First();
    return value.Select(item => Convert.ChangeType(item, containedType)).ToList();
}
公共静态对象转换列表(列表值,类型)
{
var containedType=type.GenericTypeArguments.First();
返回值.Select(item=>Convert.ChangeType(item,containedType)).ToList();
}
用法示例:

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

ConvertList(objects, typeof(List<int>)).Dump();
var objects=新列表{1,2,3,4};
ConvertList(objects,typeof(List)).Dump();
我不确定这有多有用…我想它突出了非常有用的Convert.ChangeType方法


更新:由于其他人正确地指出,这实际上不会返回
列表(其中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 });
}
publicstaticobjectconvertlist(列表项,类型,boolperformconversion=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 itemsToCast;
if(性能转换)
{
itemsToCast=items.Select(item=>Convert.ChangeType(item,containedType));
}
其他的
{
itemsToCast=项目;
}
var castedItems=castMethod.Invoke(null,new[]{itemsToCast});
返回toListMethod.Invoke(null,new[]{castedItems});
}
如果不需要转换(因此每个值的类型实际上是正确的,并且字符串中没有int等),则删除
performConversion
标志和关联的块


示例:

//
///将项目列表转换为新类型的类型化项目列表
/// 
///

//考虑源列表,NetryMeType是Type(String),因此结果列表有类型列表
///
///新项目类型 ///对象列表 ///类型化列表对象 公共静态IList ConvertList(类型newItemType,IList源) { var listType=类型(列表); Type[]typeArgs={newItemType}; var genericListType=listType.MakeGenericType(typeArgs); var typedList=(IList)Activator.CreateInstance(genericListType); foreach(源中的var项) { 类型列表。添加(项目); } 返回类型列表; }
这里有一个扩展方法与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;
}
公共静态IList CastToList(此IEnumerable源代码,类型为itemType)
{
var listType=typeof(List).MakeGenericType(itemType);
var list=(IList)Activator.CreateInstance(listType);
foreach(来源中的var项目)列表。添加(项目);
退货清单;
}
用法:

var list = new List<object>();
list.add(1);
list.add(2);
var boxedIntList = list.CastToList(typeof(int)); //type is object{List<int>}
var list=newlist();
增加第(1)款;
增加(2);
var boxedIntList=list.CastToList(typeof(int));//类型为对象{list}

我怎么能理解我应该调用ConvertList?我只知道Type,我不能键入ConvertList我怎么能理解我应该调用ConvertList?我只知道Type,我不能键入ConvertList我明白了,那么你需要在运行时使用反射来生成泛型类型,参见Guillaume的答案(我不会重复)。是的,这是一个很好的解决方案。在这里找到了好的线程-我不确定这对OP提到的类型是否有效(至少是bool和int),因为要创建一个对象列表,首先值类型已装箱,因此无法添加到列表中。编辑:实际上这不是问题。您需要更改
Type[]typeArgs={type};
在方法中,to
type[]typeArgs={type.GenericTypeArguments.First()}
;@Richiban您是对的,我错误地将
类型
预期为项目的类型。修复此操作不会创建特定类型的通用列表。它只是将内部元素转换为特定类型,但列表本身仍然是
列表
。请参阅:只是为了摆脱神奇字符串
“Cast”
“ToList”
您可以将它们替换为
nameof(Enumerable.Cast)
nameof(Enumerable)。
var objects = new List<Object> { 1, 2, 3, 4 };

ConvertList(objects, typeof(List<int>)).Dump();
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 });
}
    /// <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 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>}