developer tip

생성자를 호출하지 않고 객체 인스턴스를 만드시겠습니까?

copycodes 2020. 11. 28. 09:39
반응형

생성자를 호출하지 않고 객체 인스턴스를 만드시겠습니까?


C #에서 생성자를 호출하지 않고 클래스의 인스턴스를 인스턴스화하는 방법이 있습니까?

클래스가 공용이고 타사 라이브러리에 정의되어 있고 생성자가 내부라고 가정합니다. 내가 이것을하고 싶은 이유는 복잡하지만 어떤 종류의 C # 해커를 사용할 수 있는지 아는 것이 도움이 될 것입니다.

참고 : 특별히 생성자를 호출하고 싶지 않으므로 리플렉션을 사용하여 내부 생성자에 액세스하는 것은 옵션이 아닙니다.


나는 이것을 시도하지 않았지만 deserialization 중에 사용되는 FormatterServices.GetUninitializedObject 라는 메서드 가 있습니다.

MSDN의 의견은 다음과 같습니다.

개체의 새 인스턴스가 0으로 초기화되고 생성자가 실행되지 않기 때문에 개체는 해당 개체에서 유효한 것으로 간주되는 상태를 나타내지 않을 수 있습니다.


실제로 생성자를 내부로 만든 것처럼 들리므로 인스턴스화 할 수 없습니다. 빌더 또는 공장 방법이있을 수 있습니다.

다음 기사를 확인하십시오.

제 3 자 파생 방지 : 1 부

제 3 자 파생 방지 : 2 부

추론을 설명합니다.


많은 사람들이 믿는 것과는 달리 생성자는 객체의 인스턴스화와 전혀 관련이 없습니다 (꽤 오해의 소지가있는 용어). 생성자는 개체를 인스턴스화 한 후 해당 개체가 자신을 적절하게 초기화 할 수 있도록 호출 할 수있는 특수 메서드입니다. C ++ 개체 인스턴스화에서는 개체에 대한 메모리를 할당합니다. .NET 및 Java에서는 필드 유형 (0, null, false 등)에 따라 기본값으로 할당되고 미리 초기화됩니다. 그런 다음 런타임은 생성자를 호출합니다. 새 연산자는이 두 가지 개별 작업을 단일 작업으로 보이는 작업으로 캡슐화합니다. 생성자를 사용하지 않고 인스턴스를 만들 수 없다면 역 직렬화는 .NET에서 작동 할 수 없었습니다. 즉, 소위 ConstructorInfo 유형은 Invoke (...)를 호출 할 때 새 연산자와 생성자 역할을 모두 수행합니다.


리플렉션을 통해 생성자에 액세스하고 그렇게 호출하는 것이 가능할 수도 있습니다 (하지만 생성자가 내부이기 때문에 작동할지 확신 할 수 없습니다. 테스트해야합니다). 그렇지 않으면 내 지식으로 생성자를 호출하지 않고는 객체를 만들 수 없습니다.


System.Activator.CreateInstance 함수를 참조하십시오.


편집 : 질문을 업데이트했으며 생성자없이 클래스를 생성하려고합니다. 또는 기본 "빈 생성자"를 호출합니다.

이미 지정된 생성자가있는 경우 컴파일러가 기본 생성자를 생성하지 않기 때문에이 작업을 수행 할 수 없습니다. 그러나 독자의 이익을 위해 내부, 보호 또는 개인 생성자를 얻는 방법은 다음과 같습니다.

클래스가 Foo라고 가정합니다.

using System.Reflection;

// If the constructor takes arguments, otherwise pass these as null
Type[] pTypes = new Type[1];
pTypes[0] = typeof(object);    
object[] argList = new object[1];
argList[0] = constructorArgs;

ConstructorInfo c = typeof(Foo).GetConstructor
    (BindingFlags.NonPublic |
     BindingFlags.Instance,
     null,
     pTypes,
     null);

Foo foo = 
    (Foo) c.Invoke(BindingFlags.NonPublic,
                   null, 
                   argList, 
                   Application.CurrentCulture);

못 생겼지 만 작동합니다.

물론 생성자를 내부로 표시하는 데는 완벽하게 합법적 인 이유가있을 수 있으므로 클래스를 반성하여 남용하기 전에 원하는 항목의 논리를 실제로 고려해야합니다.


객체를 생성하려면 생성자를 호출해야합니다. 원하는대로 사용할 수있는 것이 없다면 Mono 프로젝트의 Cecil과 같은 바이트 코드 재 작성 라이브러리를 사용할 수 있습니다. Windows와 Linux에서 작동합니다. 내가 본 데모 중 일부에서 꽤 멋져 보였습니다. 방법 및 모든 종류의 미친 물건의 보호 수준을 변경할 수 있습니다.


클래스 (및 참조하는 개체의 클래스)가 Serializable이면 MemoryStream에 출력하는 BinaryFormatter를 사용하여 직렬화 (바이트 배열 byte [] 생성) 한 다음 역 직렬화하여 전체 복사본을 만들 수 있습니다. 객체를 바이트 배열로 변환하는 방법에 대한이 질문에 대한 답변을 참조하십시오 . (하지만 참고-나중에 / 다른 곳에서 사용하기 위해 바이트 배열을 저장하는 것은 작동하지 않을 가능성이 높습니다. IOW는 바이트 배열을 파일이나 다른 영구 형식에 저장하지 않습니다.)


당신이 요청하는 것은 관리 형 프로그래밍이 개발 된 철학을 위반하는 것입니다. .Net Framework 및 C #은 가능한 경우 개체를 기본 메모리에서 추상화해야한다는 원칙으로 구축되었습니다. 객체는 구조화 된 바이트 배열이 아닌 객체입니다. 이것이 바로 객체를 빈 포인터로 캐스트 할 수없는 이유입니다. 객체가 기본 메모리에서 추상화 될 때 생성자가 호출되지 않고 객체 인스턴스가 존재할 수 있다고 제안하는 것은 근본적으로 유효하지 않습니다.

즉, .Net 프레임 워크는 실제로 객체가 실제로 메모리에 표현된다는 사실을 양보했습니다. 약간의 창의력으로 초기화자를 호출하지 않고도 값 유형을 인스턴스화 할 수 있습니다. 그러나 그렇게해야한다고 느낀다면 아마도 일을 잘못하고있는 것입니다.


I noticed the "deadness" of the subject but just for clarification on further readers and to put a final answer that maybe wasn't possible when the question was posted. Here it goes.

It seems that you can instantiate a class without using it's constructors by assigning values to its properties. Here is the address where is the how-to in MSDN for this type of instantiation http://msdn.microsoft.com/en-us/library/bb397680.aspx.

It seems like this is a technique that's not well known because I encountered it in a article in CodeProject and then googled it and didn't find anything about it and later on visited the MSDN Homepage and there was a post that linked me to that exact subject. So it seems that it's an unknown subject rather than a new one because the date on the CodeProject post dates May 2008.

Hope this helps someone else that google's this and comes across with this question.


No one here has quite clarified what is meant by "It can't be done."

The constructor is what creates the object. Your question is akin to "How can I build a sand castle without shaping it like a castle?" You can't -- All you will have is a pile of sand.

The closest thing you could possible do is to allocate a block of memory the same size as your object:

byte[] fakeObject = new byte[sizeof(myStruct)];

(NOTE: even that will only work in MyStruct is a value type)

참고URL : https://stackoverflow.com/questions/296584/create-object-instance-without-invoking-constructor

반응형