15

직장에서 기존 코드를 읽으면 어떻게 작동 할 수 있는지 궁금해졌습니다. 어셈블리에 정의 된 클래스가 있습니다.

[Serializable]
public class A
{
    private readonly string _name;
    private A(string name)
    {
        _name = name;
    }
}

그리고 다른 어셈블리에서 :

public void f(Type t) {
    object o = Activator.CreateInstance(t);
}

그 간단한 전화f(typeof(A))

나는 AFAIK가 ctor가 선언되면 컴파일러가 기본 public parameterless 생성자를 생성하지 않아야하므로 매개 변수없는 생성자가 없다는 예외를 예상했다.

이 코드는 .NET 2.0에서 실행됩니다.

[편집] 죄송하지만 실제 코드를 잘못 읽었습니다 ... 제가 제공 한 샘플에서는 설명하지 않았습니다. 나는 정보의 좋은 부분을 제공했기 때문에 JonH 대답을 수락했다.


  • @Codesleuth - 가끔은이 규칙을 기억하면 가끔 이주자가 생깁니다. 답변은 아래를 참조하십시오. - JonH

4 답변


9

이것 좀 봐:리플렉션을 사용하여 C #에서 기본 생성자없이 형식의 인스턴스 만들기

다음은 앞으로도 C #4.0과 관련됩니다.

Microsoft에서 2010 년 1 월 4 일에 게시 됨   오후 2:08

귀하의 버그 및   그 행동이   당신은 설명 된대로 설계되었습니다. 우리는 지금   이 문제를 보관합니다. 사용 해줘서 고마워.   Visual Studio 및 .Net Framework!

Activator.CreateInstance에는 많은 오버로드가 있습니다.     단일 형식 매개 변수 만 사용합니다.     디폴트의 매개 변수를 호출합니다.     건설자. 가져 오는 생성자     선택 매개 변수는     귀하의 예제는 기본값이 아닙니다.     생성자. 그들을 호출하려면     에:

  1. 인수 배열을 사용하는 오버로드 사용
  2. 인수로 Type.Missing 전달
  3. BindingFlags에서 OptionalParamBinding을 지정하십시오.

다음은 그 예입니다.

Activator.CreateInstance(typeof(MyClassName),
 BindingFlags.CreateInstance |
 BindingFlags.Public |
 BindingFlags.Instance |
 BindingFlags.OptionalParamBinding,
 null, new Object[] {Type.Missing}, null);

감사,

와타 우수

Microsoft Corp.


  • 그래서 Seb가 클래스를 정의했을 수도 있습니다.A다른 위치에 있거나로드중인 어셈블리가 업데이트되지 않습니다. 코드 이상이 아니라 프로젝트 / 솔루션 문제와 같은 것 같습니다. - Codesleuth
  • @Codesleuth - 아마도. - JonH

22

대안은 다음과 같습니다.

object obj = System.Runtime.Serialization.FormatterServices
          .GetUninitializedObject(t);

이것은 메모리에 객체를 생성하지만하지 않는다생성자를 실행하십시오. 무서운.


  • ~이다.매우 무서운. 그리고 정확하게 내가 필요로했던 것! +1 - ashes999
  • 일반적으로 seriaizers, 프록시 (RPC), orms에서만 사용되는 @ashes - Marc Gravell
  • 그것은 내 간단한 테스트 dll 형식 var에 근무했습니다. 하지만 여러 클래스, 메서드 등 귀하의 라인 추락과 함께 더 복잡한 DLL을. System.MemberAccessException 유형의 처리되지 않은 예외입니다. mscorlib.dll에서 발생했습니다. 추가 정보 : 추상 클래스를 만들 수 없습니다. - humudu
  • @humudu 예, 생성자를 우회하여 추상 형식을 만들 수 없습니다. 이는 런타임에서 지원하지 않는 것입니다. 추상적 인 인스턴스를 만들 수 있다면, 무언가가 매우 파괴됩니다. - Marc Gravell
  • 처음에로드 한 메소드와는 별도로 런타임에 결정된 dll 메소드에 액세스하여 실행하려고합니다. 나중에 객체 속성으로 변환하여 나중에 액세스하려고 시도했지만, 기회가 있으면 제안 해 주시겠습니까? - humudu

0

이것은 가능하지 않을 수도 있지만 가장 간단한 방법은 인수 목록을 다음과 같은 형식으로 전달하는 것입니다.

Activator.CreateInstance (t, "name");

f ()가 실제로하려고하는 것에 대해 생각하고 싶을 것입니다. A 유형의 객체를 인스턴스화해야합니까? 어떤 다른 클래스를 인스턴스화할까요?

한 가지 가능성은 클래스 A에 대한 CreateInstance ()에 올바른 매개 변수를 전달하는 f () 내에서 switch 문을 사용하는 것입니다.이 작업은 확장되지는 않지만 문제가되지는 않습니다.


0

두 가지 혼란스러운 맛이 있습니다.CreateInstance:목적유형System.Type~로서매개 변수, 다른 하나는유형 매개 변수 T.

첫 번째:

object Activator.CreateInstance(type As Type) { }

두번째 것:

T Activator.CreateInstance<T>() { }

그만큼둘째하나는 공개 매개 변수없는 생성자가없는 클래스에서 작동하지 않는 클래스입니다.

두 번째 것을 사용하는 것은 거의 결코 의미가 없다는 점에 유의하십시오. 어떤 경우 에든 그것이 사용될 것이면,where T : new()클래스에 대한 제약 조건을 사용하고T의 생성자.

그만큼MSDN 설명서동의 함 :

일반적으로,CreateInstance응용 프로그램 코드에서,   형식을 알고 있어야하기 때문에   컴파일 시간. 유형을 알고있는 경우   컴파일 시간, 일반적인 인스턴스 생성   구문을 사용할 수 있습니다 (new~에있는 연산자   기음#,NewVisual Basic에서,gcnew...에서   C ++).

편집하다나는 너무 빨리 말할지도 모릅니다. 첫 번째 버전도 작동하지 않는 것으로 보입니다.


  • 예, 첫 번째 버전에서 같은 오류가 발생합니다.이 객체에 대해 정의 된 매개 변수없는 생성자가 없습니다. - Evan

연결된 질문


관련된 질문

최근 질문