使用反射</object>将<List>转换为未知T []

时间:2013-06-14 17:29:25

标签: c# reflection casting

我在另一个问题上找到了类似的东西,但我无法解决我的问题,因为我在c#中还是很新。

我有

System.Type type; // for example int[]
System.Type elementType = type.GetElementType(); //for example int

和我需要转换为int []

的List
object valueObj; //is my List<object> i want to cast to int[]

我正在尝试以下方法:

MethodInfo castMethod = typeof(Enumerable).GetMethod("Cast")
    .MakeGenericMethod( new System.Type[]{ elementType } );
MethodInfo toArrayMethod = typeof(Enumerable).GetMethod("ToArray")
     .MakeGenericMethod( new System.Type[]{ elementType } );

var castedObjectEnum = castMethod.Invoke(null, new object[] { valueObj });
var castedObject = toArrayMethod.Invoke(null, new object[] { castedObjectEnum });

在最后一行我得到了这个运行时异常

InvalidCastException:无法从源类型转换为目标类型。 System.Linq.Enumerable + c__Iterator0 1[System.Int32].MoveNext () System.Collections.Generic.List 1 [System.Int32] .AddEnumerable(IEnumerable`1 enumerable)

作为最后一件事我需要使用

将casteObject分配给privateField
field.SetValue(this, castedObject);

编辑: 我将尝试获取更多信息,但为了更好地解释我正在尝试做什么,我将解释用例。

我在json的某些类字段中序列化到磁盘,然后当我反序列化时,我得到一个List,其中我序列化一个int / bools / string的基本数组

我正在通过使用自定义属性标记字段来进行序列化和反序列化,并且我希望能够序列化任何基本类型的数组和列表

我会仔细检查并获得更多信息

2 个答案:

答案 0 :(得分:3)

我不知道你做错了什么。

这是一个演示的LINQPad程序,它似乎使用了你所做的相同调用,但我得到了正确类型数组的输出。

void Main()
{
    object valueObj = new List<object> { 1, 2, 3 };
    Type type = typeof(int[]);

    Type elementType = type.GetElementType();
    MethodInfo castMethod = typeof(Enumerable).GetMethod("Cast")
        .MakeGenericMethod( new System.Type[]{ elementType } );
    MethodInfo toArrayMethod = typeof(Enumerable).GetMethod("ToArray")
        .MakeGenericMethod( new System.Type[]{ elementType } );

    var castedObjectEnum = castMethod.Invoke(null, new object[] { valueObj });
    var castedObject = toArrayMethod.Invoke(null, new object[] { castedObjectEnum });
    castedObject.Dump();
}

得到一个对应于int数组的输出。发布的代码似乎工作得很好。你的问题必须在其他地方。可能是你实际上没有发送属性List<object>或列表中包含的东西不是int?

只需更改此行:

object valueObj = new List<object> { 1, 2, 3 };

到此:

object valueObj = new List<object> { 1, 2, 3, "Test" };

给我这个例外。

也许你想要OfType而不是Cast

如果替换castMethod检索中的字符串,它再次“有效”,但当然会过滤掉该字符串。

此处需要更多信息。

答案 1 :(得分:1)

嗯,你有源List<object>,可以得到它的长度。

您可以使用您的类型和长度来呼叫Array.CreateInstance。然后你所要做的就是逐个移动物品。

为什么要使用linq?