문제

컴파일 타임에 알려지지 않은 유형의 배열을 필사적으로 만들려고 노력하고 있습니다. 런타임에 나는 유형을 발견했지만 인스턴스를 만드는 방법을 모르겠습니다.

같은 것 :

Object o = Activator.CreateInstance(type);

매개 변수가없는 생성자가 없기 때문에 작동하지 않으며 배열에는 생성자가없는 것 같습니다.

도움이 되었습니까?

해결책

다른 팁

배열의 CreateInstance 오버로드 중 하나를 사용할 수 있습니다.

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

꽤 오래된 게시물이지만 새로운 질문에 대답하면서 다차원 배열을 작성하는 관련 예제를 게시합니다.

유형을 가정합니다 (elementType) 처럼 int 예를 들어 2 차원 배열.

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

예를 들어 2 차원이면

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 당신은 할 수 있습니다

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 당신이 지나가는 것이 요소 유형 자체라면.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top