Linq使用System.Type </t>转换<t>

时间:2010-08-10 13:19:16

标签: linq casting

LinQ包含强制转换方法,该方法会将列表中的每个条目强制转换为 T 。假设我们有一个如下所示的列表:

List<Object> obj = new List<Object>();
obj.Add("A");
obj.Add("B");

工作演员可能

var list = obj.Cast<string>();

我想做什么

Type t = typeof(String);
Object list = obj.Cast(t);

解决方案是使用反射并通用创建列表并填充它但我想知道是否有更好的解决方案?听说.NET 4.0应该支持一些共同/反差,这可能是一种方法。


额外信息和反思洗脱

我得到的错误是以下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;
    }

3 个答案:

答案 0 :(得分:4)

我不太明白你为什么要这样做但你可以通过反思来调用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 });

在这种情况下,stringSequence的运行时类型将实现IEnumerable<string>

答案 1 :(得分:2)

静态执行此操作是不可能的,只能使用单个对象执行此操作。

Type t = typeof(string);
var x = (t)obj; // invalid

但是,可以动态处理元素,以便不必转换为基础类型:

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

答案 2 :(得分:0)

您不需要在仅在运行时知道的类型上投射某些内容。对象的类型不会改变,因为你将执行强制转换,如果它是字符串,它将在以后变成一个字符串,如果你将它分配给字符串或对象变量并不重要。

在使用反射方法操作时,您无需关心转换为实际对象类型。它可以作为一个对象变量保留,因为在使用反射时,无论如何都可以访问它所有的真实类型成员。