Microsoft MVP성태의 닷넷 이야기
.NET Framework: 964. C# 9.0 - (13) 모듈 이니셜라이저(Module initializers) [링크 복사], [링크+제목 복사],
조회: 20807
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 17개 있습니다.)

C# 9.0 - (13) 모듈 이니셜라이저(Module initializers)

C# 9.0 - (1) 대상으로 형식화된 new 식(Target-typed new expressions)
; https://www.sysnet.pe.kr/2/0/12363

C# 9.0 - (2) localsinit 플래그 내보내기 무시(Suppress emitting localsinit flag)
; https://www.sysnet.pe.kr/2/0/12364

C# 9.0 - (3) 람다 메서드의 매개 변수 무시(Lambda discard parameters)
; https://www.sysnet.pe.kr/2/0/12365

C# 9.0 - (4) 원시 크기 정수(Native ints)
; https://www.sysnet.pe.kr/2/0/12366

C# 9.0 - (5) 로컬 함수에 특성 지정 가능(Attributes on local functions)
; https://www.sysnet.pe.kr/2/0/12372

C# 9.0 - (6) 함수 포인터(Function pointers)
; https://www.sysnet.pe.kr/2/0/12374

C# 9.0 - (7) 패턴 일치 개선 사항(Pattern matching enhancements)
; https://www.sysnet.pe.kr/2/0/12383

C# 9.0 - (8) 정적 익명 함수 (static anonymous functions)
; https://www.sysnet.pe.kr/2/0/12389

C# 9.0 - (9) 레코드 (Records)
; https://www.sysnet.pe.kr/2/0/12392

C# 9.0 - (10) 대상으로 형식화된 조건식(Target-typed conditional expressions)
; https://www.sysnet.pe.kr/2/0/12399

C# 9.0 - (11) 공변 반환 형식(Covariant return types)
; https://www.sysnet.pe.kr/2/0/12402

C# 9.0 - (12) foreach 루프에 대한 GetEnumerator 확장 메서드 지원(Extension GetEnumerator)
; https://www.sysnet.pe.kr/2/0/12403

C# 9.0 - (13) 모듈 이니셜라이저(Module initializers)
; https://www.sysnet.pe.kr/2/0/12404

C# 9.0 - (14) 부분 메서드에 대한 새로운 기능(New features for partial methods)
; https://www.sysnet.pe.kr/2/0/12405

C# 9.0 - (15) 최상위 문(Top-level statements)
; https://www.sysnet.pe.kr/2/0/12406

C# 9.0 - (16) 제약 조건이 없는 형식 매개변수 주석(Unconstrained type parameter annotations)
; https://www.sysnet.pe.kr/2/0/12423




(이번 실습은 - 오늘 기준 16.7.7의 Visual Studio 2019에서 지원하지 않으므로 Visual Studio Preview 버전으로 실습해야 합니다.)

예전에, 닷넷 어셈블리에서 숨겨진 <Module> 클래스에 대한 설명을 한 적이 있습니다.

닷넷 - <Module> 클래스의 용도
; https://www.sysnet.pe.kr/2/0/11335

아울러 C# 언어에서는 <Module> 클래스의 내용을 제어할 수 없다고 했는데요, 이것을 C# 9.0부터 허용하기로 했습니다. 방법은, System.Runtime.CompilerServices 네임스페이스의 ModuleInitializerAttribute 특성을,

ModuleInitializerAttribute Class
; https://learn.microsoft.com/en-us/dotnet/api/system.runtime.compilerservices.moduleinitializerattribute

여러분들이 작성한 static 메서드에 적용하기만 하면 됩니다.

using System;
using System.Runtime.CompilerServices;

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Main");
    }
}

class Module
{
    [ModuleInitializer]
    internal static void DllMain()
    {
        Console.WriteLine("DllMain");
    }
}

#if !NET5_0
// .NET 5.0 환경이 아닌 경우 IsExternalInit 클래스를 별도로 정의해서 컴파일 가능하게 만듦
namespace System.Runtime.CompilerServices
{
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
    public sealed class ModuleInitializerAttribute : Attribute { }
}
#endif

/* 실행 결과
DllMain
Program.Main
*/

보는 바와 같이 실행 결과를 보면 Main 메서드보다 이전에 실행이 됩니다. 실제로 빌드 결과물인 EXE 파일을 역어셈블러로 열면 <Module> 클래스가 다음과 같이 바뀐 것을 확인할 수 있습니다.

using System;

internal class <Module>
{
    static <Module>()
    {
        Module.DllMain();
    }
}

결국, ModuleInitializer 특성이 적용된 메서드는 모듈이 로드되자마자 자동으로 호출이 되는 혜택을 받습니다. (굳이 C++과 비교하자면 DllMain 함수와 유사합니다.)




참고로 호출의 특성상, 몇 가지 (당연한) 제약이 있습니다.

  1. 반드시 static 메서드여야 하며,
  2. 파라미터가 없어야 하며,
  3. 반환 타입은 void만 허용되며,
  4. 제네릭 유형이 아니어야 하며,
  5. internal class <Module> 타입에서 호출이 가능해야 하므로 internal 또는 public 접근 제한자를 가져야 합니다. (이런 측면에서 로컬 함수로는 정의할 수 없습니다.)

또한, 하나의 모듈에 여러 개의 ModuleInitializer 특성을 적용한 메서드를 정의할 수 있지만 그것들이 호출되는 순서는 명시적으로 제어할 수 있는 옵션이 없으므로 특정 초기화 순서를 가정하고 만들어서는 안 됩니다.

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 3/9/2024]

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

비밀번호

댓글 작성자
 




... 46  47  48  49  50  51  52  53  54  55  [56]  57  58  59  60  ...
NoWriterDateCnt.TitleFile(s)
12571정성태3/21/202117011오류 유형: 706. WSL 2 기반으로 "Enable Kubernetes" 활성화 시 초기화 실패 [1]
12570정성태3/19/202122734개발 환경 구성: 555. openssl - CA로부터 인증받은 새로운 인증서를 생성하는 방법
12569정성태3/18/202122927개발 환경 구성: 554. WSL 인스턴스 export/import 방법 및 단축 아이콘 설정 방법
12568정성태3/18/202115881오류 유형: 705. C# 빌드 - Couldn't process file ... due to its being in the Internet or Restricted zone or having the mark of the web on the file.
12567정성태3/17/202118545개발 환경 구성: 553. Docker Desktop for Windows를 위한 k8s 대시보드 활성화 [1]
12566정성태3/17/202118234개발 환경 구성: 552. Kubernetes - kube-apiserver와 REST API 통신하는 방법 (Docker Desktop for Windows 환경)
12565정성태3/17/202114904오류 유형: 704. curl.exe 실행 시 dll not found 오류
12564정성태3/16/202115746VS.NET IDE: 160. 새 프로젝트 창에 C++/CLI 프로젝트 템플릿이 없는 경우
12563정성태3/16/202118644개발 환경 구성: 551. C# - JIRA REST API 사용 정리 (3) jira-oauth-cli 도구를 이용한 키 관리
12562정성태3/15/202119114개발 환경 구성: 550. C# - JIRA REST API 사용 정리 (2) JIRA OAuth 토큰으로 API 사용하는 방법파일 다운로드1
12561정성태3/12/202117971VS.NET IDE: 159. Visual Studio에서 개행(\n, \r) 등의 제어 문자를 치환하는 방법 - 정규 표현식 사용
12560정성태3/11/202119167개발 환경 구성: 549. ssh-keygen으로 생성한 PKCS#1 개인키/공개키 파일을 각각 PKCS8/PEM 형식으로 변환하는 방법
12559정성태3/11/202119495.NET Framework: 1028. 닷넷 5 환경의 Web API에 OpenAPI 적용을 위한 NSwag 또는 Swashbuckle 패키지 사용 [2]파일 다운로드1
12558정성태3/10/202118590Windows: 192. Power Automate Desktop (Preview) 소개 - Bitvise SSH Client 제어 [1]
12557정성태3/10/202116747Windows: 191. 탐색기의 보안 탭에 있는 "Object name" 경로에 LEFT-TO-RIGHT EMBEDDING 제어 문자가 포함되는 문제
12556정성태3/9/202114482오류 유형: 703. PowerShell ISE의 Debug / Toggle Breakpoint 메뉴가 비활성 상태인 경우
12555정성태3/8/202118349Windows: 190. C# - 레지스트리에 등록된 DigitalProductId로부터 라이선스 키(Product Key)를 알아내는 방법파일 다운로드2
12554정성태3/8/202117818.NET Framework: 1027. 닷넷 응용 프로그램을 위한 PDB 옵션 - full, pdbonly, portable, embedded
12553정성태3/5/202117111개발 환경 구성: 548. 기존 .NET Framework 프로젝트를 .NET Core/5+ 용으로 변환해 주는 upgrade-assistant, try-convert 도구 소개 [4]
12552정성태3/5/202116897개발 환경 구성: 547. github workflow/actions에서 Visual Studio Marketplace 패키지 등록하는 방법
12551정성태3/5/202115452오류 유형: 702. 비주얼 스튜디오 - The 'CascadePackage' package did not load correctly. (2)
12550정성태3/5/202115316오류 유형: 701. Live Share 1.0.3713.0 버전을 1.0.3884.0으로 업데이트 이후 ContactServiceModelPackage 오류 발생하는 문제
12549정성태3/4/202116756오류 유형: 700. VsixPublisher를 이용한 등록 시 다양한 오류 유형 해결책
12548정성태3/4/202117920개발 환경 구성: 546. github workflow/actions에서 nuget 패키지 등록하는 방법
12547정성태3/3/202118432오류 유형: 699. 비주얼 스튜디오 - The 'CascadePackage' package did not load correctly.
12546정성태3/3/202118455개발 환경 구성: 545. github workflow/actions에서 빌드시 snk 파일 다루는 방법 - Encrypted secrets
... 46  47  48  49  50  51  52  53  54  55  [56]  57  58  59  60  ...