如何在运行时创建任意Array类型的实例?

我正在尝试在编译时反序列化未知类型的数组。 在运行时我发现了类型,但我不知道如何创建实例。

就像是:

Object o = Activator.CreateInstance(type); 

这是行不通的,因为没有无参数构造函数,Array似乎没有任何构造函数。

使用Array.CreateInstance 。

您可以使用Array的CreateInstance重载之一,例如: –

 object o = Array.CreateInstance(type, 10); 

相当古老的post,但在回答一个新问题时,虽然发布了创建多维数组的相关示例。

假设类型( elementType )为int ,例如二维数组。

 var size = new[] { 2, 3 }; var arr = Array.CreateInstance(typeof(int), size); 

例如,当它是二维时,它可以填充为

 var value = 1; for (int i = 0; i < size[0]; i++) for (int j = 0; j < size[1]; j++) arr.SetValue(value++, new[] { i, j }); //arr = [ [ 1, 2, 3 ], [ 4, 5, 6 ] ] 

另一种方法是使用表达式树来提高性能。 例如,如果您有arrays类型 ,请type

 var ctor = type.GetConstructors().First(); // or find suitable constructor var argsExpr = ctor.GetParameters().Select(x => Expression.Constant(0)); var func = Expression.Lambda>(Expression.New(ctor, argsExpr)).Compile(); 

这只返回一个空数组。 可能不是很有用。 MSDN声明GetConstructors不保证任何顺序,因此您可能需要一个逻辑来查找具有正确参数的正确构造函数,以便以正确的大小进行实例化。 例如你可以这样做:

 static Func ArrayCreateInstance(Type type, params int[] bounds) // can be generic too { var ctor = type .GetConstructors() .OrderBy(x => x.GetParameters().Length) // find constructor with least parameters .First(); var argsExpr = bounds.Select(x => Expression.Constant(x)); // set size return Expression.Lambda>(Expression.New(ctor, argsExpr)).Compile(); } 

使用Expression.NewArrayBounds而不是Expression.New可以更容易地实现相同的function,如果您只获得了数组元素类型而不是数组类型本身,则更多。 演示:

 static Func ArrayCreateInstance(Type type, params int[] bounds) // can be generic too { var argsExpr = bounds.Select(x => Expression.Constant(x)); // set size var newExpr = Expression.NewArrayBounds(type.GetElementType(), argsExpr); return Expression.Lambda>(newExpr).Compile(); } // this exercise is pointless if you dont save the compiled delegate, but for demo purpose: x = string[] {... y = ArrayCreateInstance(x.GetType(), 10)(); // you get 1-d array with size 10 x = string[,,] {... y = ArrayCreateInstance(x.GetType(), 10, 2, 3)(); // you get 3-d array like string[10, 2, 3] x = string[][] {... y = ArrayCreateInstance(x.GetType(), 10)(); // you get jagged array like string[10][] 

只需更改type.GetElementType()即可type您传递的内容是元素类型本身。