Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

override 메서드가 정의된 타입의 인스턴스로 base 메서드를 호출하는 방법 - 두 번째 이야기

이번 글은 다음의 글에 대한 보강입니다. ^^

override 메서드가 정의된 타입의 인스턴스로 base 메서드를 호출하는 방법
; https://www.sysnet.pe.kr/2/0/1564

위의 글에서는 DynamicMethod를 이용해 callvirt를 call로 강제 지정하는 방법을 사용하고 있는데요. 이 기법을 .NET 1.1에서 사용하려면 어떻게 해야 할까요? ^^

아쉽게도 DynamicMethod는 .NET 2.0부터 지원되기 때문에 1.1 이하에서는 사용할 수 없습니다. (물론, 1.1 용으로 아직도 응용 프로그램을 만드는 경우는 거의 없겠지만.)

이에 대해 혹시나 또 누군가 친절하게 방법을 만들어 두지 않았을까 검색해 보았는데... 아쉽게도 이번에는 꽝이군요. ^^

C# .NET 1.1 - MethodBase.Invoke on virtual methods (dynamic method lookup)
; http://www.codeproject.com/Messages/1618442/Csharp-NET-1-1-MethodBase-Invoke-on-virtual-method.aspx

방법이 없을까...? 생각하다가 한 가지 아이디어가 떠 올랐습니다. 혹시 제가 무슨 생각을 한 것인지 상상이 가시나요? ^^

힌트를 하나 드리자면, 다음과 같이 테스트 코드를 만드는 것으로 시작할 수 있습니다.

using System;

namespace ConsoleApplication1
{
    class BaseClass
    {
        public virtual void Do()
        {
            Console.WriteLine("BaseClass.Do");
        }
    }

    class DerivedClass : BaseClass
    {
        public override void Do()
        {
            Console.WriteLine("DerivedClass.Do");

            base.Do();
        }
    }
    static class Program
    {
        static void Main(string[] args)
        {
            DerivedClass dc = new DerivedClass();
            // dc.Do();

            DirectInvoke(dc);
        }

        private static void DirectInvoke(DerivedClass dc)
        {
            dc.Do();
        }
    }
}

그러니까, 요점은 callvirt가 아닌 call을 해주면 되기 때문에 이를 IL 어셈블리를 직접 변경해서 구현할 수 있습니다. 따라서 산출된 DLL/EXE 파일에 대해 다음과 같이 IL 코드로 역어셈블을 하면,

C:\Users\bin\Debug>ildasm ConsoleApplication1.exe /OUTPUT=test.il

다음과 같은 결과물을 얻을 수 있습니다.

// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                        
  .ver 4:0:0:0
}

// ... 생략 ...

.class private auto ansi beforefieldinit ConsoleApplication1.DerivedClass
       extends ConsoleApplication1.BaseClass
{
// ... 생략 ...

  .method private hidebysig static void  DirectInvoke(class ConsoleApplication1.DerivedClass dc) cil managed
  {
    // Code size       9 (0x9)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldarg.0
    IL_0002:  callvirt   instance void ConsoleApplication1.BaseClass::Do()
    IL_0007:  nop
    IL_0008:  ret
  } // end of method Program::DirectInvoke

} // end of class ConsoleApplication1.Program

그럼, 위의 callvirt를 call로 간단하게 변경해 주고,

.method private hidebysig static void  DirectInvoke(class ConsoleApplication1.DerivedClass dc) cil managed
{
	// Code size       9 (0x9)
	.maxstack  8
	IL_0000:  nop
	IL_0001:  ldarg.0
	IL_0002:  call   instance void ConsoleApplication1.BaseClass::Do()
	IL_0007:  nop
	IL_0008:  ret
} // end of method Program::DirectInvoke

다시 IL 컴파일을 해주면,

C:\Users\bin\Debug>ilasm test.il

Microsoft (R) .NET Framework IL Assembler.  Version 4.0.30319.33440
Copyright (c) Microsoft Corporation.  All rights reserved.
Assembling 'test.il'  to EXE --> 'test.exe'
Source file is ANSI

Assembled method ConsoleApplication1.BaseClass::Do
Assembled method ConsoleApplication1.BaseClass::.ctor
Assembled method ConsoleApplication1.DerivedClass::Do
Assembled method ConsoleApplication1.DerivedClass::.ctor
Assembled method ConsoleApplication1.Program::Main
Assembled method ConsoleApplication1.Program::DirectInvoke
Creating PE file

Emitting classes:
Class 1:        ConsoleApplication1.BaseClass
Class 2:        ConsoleApplication1.DerivedClass
Class 3:        ConsoleApplication1.Program

Emitting fields and methods:
Global
Class 1 Methods: 2;
Class 2 Methods: 2;
Class 3 Methods: 2;
Resolving local member refs: 5 -> 5 defs, 0 refs, 0 unresolved

Emitting events and properties:
Global
Class 1
Class 2
Class 3
Resolving local member refs: 0 -> 0 defs, 0 refs, 0 unresolved
Writing PE file
Operation completed successfully

이제 원하는대로 다형성이 무시된 base 메서드만을 호출하게 동작합니다. ^^

C:\Users\bin\Debug>test
BaseClass.Do




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 4/21/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 76  77  78  79  80  81  82  83  84  85  86  87  [88]  89  90  ...
NoWriterDateCnt.TitleFile(s)
11769정성태11/5/201820108오류 유형: 501. 프로젝트 msbuild Publish 후 connectionStrings의 문자열이 $(ReplacableToken_...)로 바뀌는 문제
11768정성태11/2/201821195.NET Framework: 801. SOIL(Simple OpenGL Image Library) - Native DLL 및 .NET DLL 제공
11767정성태11/1/201821459사물인터넷: 55. New NodeMcu v3(ESP8266)의 IR LED (적외선 송신) 제어파일 다운로드1
11766정성태10/31/201824082사물인터넷: 54. 아두이노 환경에서의 JSON 파서(ArduinoJson) 사용법
11765정성태10/26/201820311개발 환경 구성: 420. Visual Studio Code - Arduino Board Manager를 이용한 사용자 정의 보드 선택
11764정성태10/26/201825587개발 환경 구성: 419. MIT 라이선스로 무료 공개된 Detours API 후킹 라이브러리 [2]
11763정성태10/25/201821934사물인터넷: 53. New NodeMcu v3(ESP8266)의 https 통신
11762정성태10/25/201822338사물인터넷: 52. New NodeMCU v3(ESP8266)의 http 통신파일 다운로드1
11761정성태10/25/201822287Graphics: 26. 임의 축을 기반으로 3D 벡터 회전파일 다운로드1
11760정성태10/24/201817804개발 환경 구성: 418. Azure - Runbook 내에서 또 다른 Runbook 스크립트를 실행
11759정성태10/24/201819914개발 환경 구성: 417. Azure - Runbook에서 사용할 수 있는 다양한 메서드를 위한 부가 Module 추가
11758정성태10/23/201822315.NET Framework: 800. C# - Azure REST API 사용을 위한 인증 획득 [3]파일 다운로드1
11757정성태10/19/201818613개발 환경 구성: 416. Visual Studio 2017을 이용한 아두이노 프로그램 개발(및 디버깅)
11756정성태10/19/201822084오류 유형: 500. Visual Studio Code의 아두이노 프로그램 개발 시 인텔리센스가 안 된다면?
11755정성태10/19/201823047오류 유형: 499. Visual Studio Code extension for Arduino - #include errors detected. [1]
11754정성태10/19/201819904개발 환경 구성: 415. Visual Studio Code를 이용한 아두이노 프로그램 개발 - 새 프로젝트
11753정성태10/19/201826591개발 환경 구성: 414. Visual Studio Code를 이용한 아두이노 프로그램 개발
11752정성태10/18/201819494오류 유형: 498. SQL 서버 - Database source is not a supported version of SQL Server
11751정성태10/18/201820014오류 유형: 497. Visual Studio 실행 시 그래픽이 투명해진다거나, 깨진다면?
11750정성태10/18/201818359오류 유형: 496. 비주얼 스튜디오 - One or more projects in the solution were not loaded correctly.
11749정성태10/18/201820631개발 환경 구성: 413. 비주얼 스튜디오에서 작성한 프로그램을 빌드하는 가장 쉬운 방법
11748정성태10/18/201820205개발 환경 구성: 412. Arduino IDE를 Store App으로 설치한 경우 컴파일만 되고 배포가 안 되는 문제
11747정성태10/17/201821480.NET Framework: 799. C# - DLL에도 EXE처럼 Main 메서드를 넣어 실행할 수 있도록 만드는 방법파일 다운로드1
11746정성태10/15/201820992개발 환경 구성: 411. Bitvise SSH Client의 인증서 모드에서 자동 로그인 방법파일 다운로드1
11745정성태10/15/201818249오류 유형: 495. TFS 파일/폴더 삭제 - The item [...] could not be found in your workspace, or you do not have permission to access it.
11744정성태10/15/201819931개발 환경 구성: 410. msbuild로 .pubxml 설정에 따른 배포 파일을 만드는 방법
... 76  77  78  79  80  81  82  83  84  85  86  87  [88]  89  90  ...