LinQ包含方法Cast,它将列表中的每个条目强制转换为T类型.假设我们有一个如下所示的列表:
List<Object> obj = new List<Object>();
obj.Add("A");
obj.Add("B");
Run Code Online (Sandbox Code Playgroud)
工作演员可能是
var list = obj.Cast<string>();
Run Code Online (Sandbox Code Playgroud)
我想做什么
Type t = typeof(String);
Object list = obj.Cast(t);
Run Code Online (Sandbox Code Playgroud)
一个解决方案是使用反射并通用地创建一个列表并填充它,但我想知道是否有更好的解决方案?听说.NET 4.0应该支持一些co/contra-variance,这可能是一种方法.
额外信息和反思Soulution
我得到的错误如下The model item passed into the dictionary is of type System.Collections.Generic.List1[IStatisticEntry], but this dictionary requires a model item of type System.Collections.Generic.List1[CrashStatistic+CrashEntry]
.请注意,CrashEntry实现了IStaticEntry,但无法进行转换,因为它是列表的泛型类型.
我构建了以下解决方案,我会像没有反射的东西一样:
public static object Cast(this IEnumerable list, Type type)
{
var newList = Activator.CreateInstance(typeof(List<>).MakeGenericType(type));
foreach (var item in list)
newList.GetType().GetMethod("Add").Invoke(newList, new object[] { item });
return newList;
}
Run Code Online (Sandbox Code Playgroud)
我不太明白你为什么要这样做,但你可以Enumerable.Cast<T>
通过反射调用:
List<object> objectList = new List<object> { "Foo", "Bar" };
object stringSequence = typeof(Enumerable)
.GetMethod("Cast", BindingFlags.Public | BindingFlags.Static)
.MakeGenericMethod(typeof(string))
.Invoke(null, new[] { objectList });
Run Code Online (Sandbox Code Playgroud)
在这种情况下,运行时类型stringSequence
将实现IEnumerable<string>
.
不可能静态地执行此操作,就像无法使用单个对象执行此操作一样。
Type t = typeof(string);
var x = (t)obj; // invalid
Run Code Online (Sandbox Code Playgroud)
但是,可以动态处理元素,这样就不需要强制转换为基础类型:
static void Main(string[] args)
{
List<Object> obj = new List<Object>();
obj.Add("A");
obj.Add("B");
var list = obj.Cast<dynamic>();
foreach (var item in list)
{
Console.WriteLine(item[0]);
}
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)