我正在实施某种反序列化,并在下一个问题上挣扎:
我有List<object>
和System.Reflection.Field
,FieldType
可以是List<string>
,List<int>
或List<bool>
,所以我需要转换自{ {1}}到那些类型。
List<object>
我可以单独编写每个案例,但应该有更好的方法使用反射。
答案 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
标志和关联的块。
答案 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>}