【发布时间】:2016-07-04 03:47:42
【问题描述】:
我试图在编译时反序列化一个未知类型的数组。在运行时我发现了类型,但我不知道如何创建实例。
类似:
Object o = Activator.CreateInstance(type);
这不起作用,因为没有无参数的构造函数,Array 似乎没有任何构造函数。
【问题讨论】:
标签: c# reflection compact-framework .net-2.0
我试图在编译时反序列化一个未知类型的数组。在运行时我发现了类型,但我不知道如何创建实例。
类似:
Object o = Activator.CreateInstance(type);
这不起作用,因为没有无参数的构造函数,Array 似乎没有任何构造函数。
【问题讨论】:
标签: c# reflection compact-framework .net-2.0
【讨论】:
您可以使用 Array 的 CreateInstance 重载之一,例如:-
object o = Array.CreateInstance(type, 10);
【讨论】:
相当老的帖子,但在回答一个新问题时,虽然发布了一个创建多维数组的相关示例。
假设类型(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 ] ]
【讨论】:
另一种方法是使用表达式树来提高性能。例如如果你有数组 type, type 你可以这样做
var ctor = type.GetConstructors().First(); // or find suitable constructor
var argsExpr = ctor.GetParameters().Select(x => Expression.Constant(0));
var func = Expression.Lambda<Func<object>>(Expression.New(ctor, argsExpr)).Compile();
这只是返回一个空数组。可能不是很有用。 MSDN 声明 GetConstructors 不保证任何顺序,因此您可能需要一个逻辑来找到具有正确参数的正确构造函数,以便以正确的大小进行实例化。例如你可以这样做:
static Func<object> 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<Func<object>>(Expression.New(ctor, argsExpr)).Compile();
}
使用Expression.NewArrayBounds 而不是Expression.New 可以更轻松地实现相同的目标,如果你得到的只是数组元素类型,而不是数组类型本身,它就更有效了。演示:
static Func<object> 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<Func<object>>(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。
【讨论】: