Microsoft MVP성태의 닷넷 이야기
.NET Framework: 842. .NET Reflection을 대체할 System.Reflection.Metadata 소개 [링크 복사], [링크+제목 복사],
조회: 19735
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

(시리즈 글이 11개 있습니다.)
.NET Framework: 404. 리플렉션을 이용해 닷넷 LicenseManager를 우회할 수 있는 사례
; https://www.sysnet.pe.kr/2/0/1565

.NET Framework: 428. .NET Reflection으로 다차원/Jagged 배열을 구분하는 방법
; https://www.sysnet.pe.kr/2/0/1653

.NET Framework: 537. C# - Reflection의 박싱 없이 값 형식을 다루는 방법
; https://www.sysnet.pe.kr/2/0/10866

.NET Framework: 685. C# - 구조체(값 형식)의 필드를 리플렉션을 이용해 값을 바꾸는 방법
; https://www.sysnet.pe.kr/2/0/11312

.NET Framework: 785. public으로 노출되지 않은 다른 어셈블리의 delegate 인스턴스를 Reflection으로 생성하는 방법
; https://www.sysnet.pe.kr/2/0/11583

.NET Framework: 842. .NET Reflection을 대체할 System.Reflection.Metadata 소개
; https://www.sysnet.pe.kr/2/0/11930

.NET Framework: 924. C# - Reflection으로 변경할 수 없는 readonly 정적 필드
; https://www.sysnet.pe.kr/2/0/12256

.NET Framework: 1045. C# - 런타임 시점에 이벤트 핸들러를 만들어 Reflection을 이용해 구독하는 방법
; https://www.sysnet.pe.kr/2/0/12609

.NET Framework: 1046. C# - 컴파일 시점에 참조할 수 없는 타입을 포함한 이벤트 핸들러를 Reflection을 이용해 구독하는 방법
; https://www.sysnet.pe.kr/2/0/12610

닷넷: 2155. C# - .NET 8 런타임부터 (Reflection 없이) 특성을 이용해 public이 아닌 멤버 호출 가능
; https://www.sysnet.pe.kr/2/0/13436

닷넷: 2249. C# - 부모의 필드/프로퍼티에 대해 서로 다른 자식 클래스 간에 Reflection 접근이 동작할까요?
; https://www.sysnet.pe.kr/2/0/13608




.NET Reflection을 대체할 System.Reflection.Metadata 소개

초기 .NET 1.x 시절에는 .NET DLL/EXE에 구현된 타입 정보를 알아보기 위해 Assembly.Load 메서드를 사용했는데요, 이때 해당 어셈블리가 로드되면 잠기는 문제가 발생하지만 어셈블리를 내리려면 AppDomain이 함께 내려가야 한다는 부작용으로 인해 이후 Assembly.ReflectionOnlyLoad 메서드가 나옵니다.

Assembly.ReflectionOnlyLoad
; https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.reflectiononlyload

이것은 어셈블리를 코드로써 로드하지 않고 메타데이터만 살펴볼 수 있도록 허용하므로 DLL/EXE가 잠기지 않는다는 장점이 있습니다. 그러던 것이, .NET Core가 나오면서 아예 순수 메타데이터 자체를 다룰 수 있도록 System.Reflection.Metadata가 나왔습니다. 이에 대해 검색해 보면 사용 예제가 하나 눈에 띄는데요,

Metadata Tools
; https://github.com/dotnet/metadata-tools

dotnet/metadata-tools
; https://github.com/dotnet/metadata-tools/blob/master/src/Microsoft.Metadata.Visualizer/MetadataVisualizer.cs

아쉽게도 .NET Framework 버전으로 나와 있는 데다 .NET Core에서는 일부 컴파일 오류가 발생해 직접 사용할 수가 없습니다. 그래서 ^^ 개인적으로 최대한 수정해 다음의 github 예제로 올렸습니다.

DotNetSamples/NetCore/Microsoft.Metadata.Visualizer/
; https://github.com/stjeong/DotNetSamples/tree/master/NetCore/Microsoft.Metadata.Visualizer

딱 하나, WriteForwarders를 못 옮겼는데요,

public void Visualize(int generation = -1)
{
    this.reader = (generation >= 0) ? readers[generation] : readers.Last();

    WriteModule();
    WriteTypeRef();
    WriteTypeDef();
    WriteField();
    WriteMethod();
    WriteParam();
    WriteMemberRef();
    WriteConstant();
    WriteCustomAttribute();
    WriteDeclSecurity();
    WriteStandAloneSig();
    WriteEvent();
    WriteProperty();
    WriteMethodImpl();
    WriteModuleRef();
    WriteTypeSpec();
    WriteEnCLog();
    WriteEnCMap();
    WriteAssembly();
    WriteAssemblyRef();
    WriteFile();
    //WriteForwarders();
    WriteExportedType();
    WriteManifestResource();
    WriteGenericParam();
    WriteMethodSpec();
    WriteGenericParamConstraint();

    WriteUserStrings();
    WriteStrings();
    WriteBlobs();
    WriteGuids();
}

나중에 기회 되면 손을 보겠습니다. ^^ 아니면 이 글을 읽으시는 분 중에 수정하셔서 PR 보내주셔도 좋겠고.




참고로 다음은 Microsoft.Metadata.Visualizer 예제 프로젝트를 이용해 스스로의 메타데이터를 출력한 결과입니다.

Microsoft.Metadata.Visualizer.dll
********************************************************************************
Module (0x00):
=====================================================================================================================
   Gen  Name                                        Mvid                                         EncId  EncBaseId
=====================================================================================================================
1: 0    'Microsoft.Metadata.Visualizer.dll' (#b10)  {5592d697-bdc0-4859-aced-22e20a3efaee} (#1)  nil    nil

TypeRef (0x01):
===================================================================================================================================
    Scope                     Name                                                   Namespace
===================================================================================================================================
 1: 0x23000001 (AssemblyRef)  'CompilationRelaxationsAttribute' (#921)               'System.Runtime.CompilerServices' (#11bf)
 2: 0x23000001 (AssemblyRef)  'RuntimeCompatibilityAttribute' (#987)                 'System.Runtime.CompilerServices' (#11bf)
 3: 0x23000001 (AssemblyRef)  'DebuggableAttribute' (#853)                           'System.Diagnostics' (#1185)
 4: 0x01000003 (TypeRef)      'DebuggingModes' (#1234)                               nil
 5: 0x23000001 (AssemblyRef)  'TargetFrameworkAttribute' (#87e)                      'System.Runtime.Versioning' (#a81)
...[생략]...
99: 0x23000002 (AssemblyRef)  'Stream' (#b46)                                        'System.IO' (#22a)
9a: 0x23000003 (AssemblyRef)  'PEReaderExtensions' (#1444)                           'System.Reflection.Metadata' (#236)
9b: 0x23000001 (AssemblyRef)  'Enum' (#bbc)                                          'System' (#b89)
9c: 0x23000001 (AssemblyRef)  'StringComparison' (#f98)                              'System' (#b89)

TypeDef (0x02):
=================================================================================================================================================================================================================================================================================================================
   Name                           Namespace                                EnclosingType         BaseType              Interfaces  Fields                 Methods                Attributes                                                                                       ClassSize  PackingSize
=================================================================================================================================================================================================================================================================================================================
1: '<Module>' (#221)              nil                                      nil                   nil                   nil         nil                    nil                    0                                                                                                0          0
2: 'MetadataVisualizer' (#10e5)   'Microsoft.Metadata.Visualizer' (#10c7)  nil                   0x0100000c (TypeRef)  nil         0x04000001-0x04000006  0x06000001-0x06000035  0x00100101 (AutoLayout, AnsiClass, Class, Public, Sealed, BeforeFieldInit)                       0          0
3: 'Program' (#b6a)               'Microsoft.Metadata.Visualizer' (#10c7)  nil                   0x0100000c (TypeRef)  nil         nil                    0x06000036-0x06000038  0x00100000 (AutoLayout, AnsiClass, Class, BeforeFieldInit)                                       0          0
4: 'TokenTypeComparer' (#1033)    nil                                      0x02000002 (TypeDef)  0x0100000c (TypeRef)  0x09000001  0x04000007-0x04000007  0x06000039-0x0600003b  0x00100103 (AutoLayout, AnsiClass, Class, NestedPrivate, Sealed, BeforeFieldInit)                0          0
5: '<>c' (#272)                   nil                                      0x02000002 (TypeDef)  0x0100000c (TypeRef)  nil         0x04000008-0x04000012  0x0600003c-0x06000047  0x00102103 (AutoLayout, AnsiClass, Class, NestedPrivate, Sealed, Serializable, BeforeFieldInit)  0          0
6: '<>c__DisplayClass29_0' (#fd)  nil                                      0x02000002 (TypeDef)  0x0100000c (TypeRef)  nil         0x04000013-0x04000014  0x06000048-0x06000049  0x00100103 (AutoLayout, AnsiClass, Class, NestedPrivate, Sealed, BeforeFieldInit)                0          0
7: '<>c__DisplayClass0_0' (#1c)   nil                                      0x02000003 (TypeDef)  0x0100000c (TypeRef)  nil         0x04000015-0x04000015  0x0600004a-0x0600004b  0x00100103 (AutoLayout, AnsiClass, Class, NestedPrivate, Sealed, BeforeFieldInit)                0          0

Field (0x04):
================================================================================================================================================
    Name                   Signature                                         Attributes                             Marshalling  Offset  RVA
================================================================================================================================================
 1: 'writer' (#108a)       06-12-35 (#8d5)                                   0x00000021 (Private, InitOnly)         nil          n/a     0
 2: 'readers' (#152b)      06-15-12-39-01-12-3D (#8d9)                       0x00000021 (Private, InitOnly)         nil          n/a     0
 3: 'aggregator' (#111f)   06-12-41 (#8e1)                                   0x00000021 (Private, InitOnly)         nil          n/a     0
...[생략]...
13: '<>4__this' (#140a)    06-12-08 (#95b)                                   0x00000006 (Public)                    nil          n/a     0
14: 'displayTable' (#425)  06-02 (#95f)                                      0x00000006 (Public)                    nil          n/a     0
15: 'args' (#1405)         06-1D-0E (#962)                                   0x00000006 (Public)                    nil          n/a     0

Method (0x06, 0x1C):
=======================================================================================================================================================================================================================================================================================================================
    Name                                   Signature                                                        RVA         Parameters             GenericParameters      ImplAttributes                                                                     Attributes  ImportAttributes  ImportName  ImportModule
=======================================================================================================================================================================================================================================================================================================================
 1: '.ctor' (#1144)                        20-02-01-12-35-15-12-39-01-12-3D (#966)                          0x00002050  0x08000001-0x08000002  nil                    0x00001881 (PrivateScope, Private, HideBySig, SpecialName, RTSpecialName)          0           0                 nil         nil
 2: '.ctor' (#1144)                        20-02-01-12-3D-12-35 (#972)                                      0x000020DD  0x08000003-0x08000004  nil                    0x00001886 (PrivateScope, Public, HideBySig, SpecialName, RTSpecialName)           0           0                 nil         nil
 3: '.ctor' (#1144)                        20-02-01-15-12-39-01-12-3D-12-35 (#97a)                          0x000020F9  0x08000005-0x08000006  nil                    0x00001886 (PrivateScope, Public, HideBySig, SpecialName, RTSpecialName)           0           0                 nil         nil
 4: 'VisualizeAllGenerations' (#1470)      20-00-01 (#6)                                                    0x00002108  nil                    nil                    0x00000086 (PrivateScope, Public, HideBySig)                                       0           0                 nil         nil
...[생략]...
49: '<TokenList>b__0' (#11e)               20-01-0E-11-80-89 (#a55)                                         0x0000487A  0x08000033-0x08000033  nil                    0x00000083 (PrivateScope, Assembly, HideBySig)                                     0           0                 nil         nil
4a: '.ctor' (#1144)                        20-00-01 (#6)                                                    0x00004893  nil                    nil                    0x00001886 (PrivateScope, Public, HideBySig, SpecialName, RTSpecialName)           0           0                 nil         nil
4b: '<Main>b__0' (#113)                    20-01-02-0E (#a5c)                                               0x0000489C  0x08000034-0x08000034  nil                    0x00000083 (PrivateScope, Assembly, HideBySig)                                     0           0                 nil         nil

Param (0x08):
=====================================================================================
    Name                       Seq#  Attributes                         Marshalling
=====================================================================================
 1: 'writer' (#108a)           1     0                                  nil
 2: 'readers' (#152b)          2     0                                  nil
...[생략]...
31: 'h' (#afc)                 1     0                                  nil
32: 'h' (#afc)                 1     0                                  nil
33: 'h' (#afc)                 1     0                                  nil
34: 'x' (#1781)                1     0                                  nil

MemberRef (0x0a):
============================================================================================================================================================
     Parent                 Name                                         Signature
============================================================================================================================================================
  1: 0x01000001 (TypeRef)   '.ctor' (#1144)                              20-01-01-08 (#1)
  2: 0x01000002 (TypeRef)   '.ctor' (#1144)                              20-00-01 (#6)
  3: 0x01000003 (TypeRef)   '.ctor' (#1144)                              20-01-01-11-11 (#a)
...[생략]...
13d: 0x01000022 (TypeRef)   'op_Implicit' (#1633)                        00-01-11-49-11-80-89 (#8b2)
13e: 0x01000072 (TypeRef)   'Equals' (#1414)                             00-03-02-0E-0E-11-82-71 (#8ba)

Constant (0x0b):
=================================================================
   Parent              Type                  Value
=================================================================
1: 0x08000007 (Param)  0x00000008 (Int32)    FF-FF-FF-FF (#8cc)
2: 0x0800001c (Param)  0x00000002 (Boolean)  01 (#8d1)
3: 0x08000021 (Param)  0x00000002 (Boolean)  00 (#8d3)

CustomAttribute (0x0c):
=========================================================================================================================================================================================================================
    Parent                 Constructor             Value
=========================================================================================================================================================================================================================
 1: 0x20000001 (Assembly)  0x0a000001 (MemberRef)  01-00-08-00-00-00-00-00 (#a65)
 2: 0x20000001 (Assembly)  0x0a000002 (MemberRef)  01-00-01-00-54-02-16-57-72-61-70-4E-6F-6E-45-78-63-65-70-74-69-6F-6E-54-68-72-6F-77-73-01 (#a6e)
...[생략]...
 d: 0x02000007 (TypeDef)   0x0a00000c (MemberRef)  01-00-00-00 (#b12)
 e: 0x08000008 (Param)     0x0a00000b (MemberRef)  01-00-00-00 (#b12)
 f: 0x08000009 (Param)     0x0a00000b (MemberRef)  01-00-00-00 (#b12)

StandAloneSig (0x11):
===================================================================================================
    Signature
===================================================================================================
 1: 07-02-02-15-12-4D-01-12-3D (#24)
 2: 07-02-08-02 (#d7)
 3: 07-01-02 (#ef)
...[생략]...
2b: 07-0A-12-1C-02-1D-0E-08-0E-12-81-B1-12-81-B5-12-3D-12-08-12-81-B9 (#80f)
2c: 07-02-11-5D-08 (#866)

Property (0x15, 0x17, 0x18):
===============================================================
   Name              Get                     Set  Attributes
===============================================================
1: 'IsDelta' (#26a)  0x06000006 (MethodDef)  nil  0

TypeSpec (0x1b):
===============================================
    Name
===============================================
 1: 15-12-79-01-1E-00 (#15)
 2: 15-12-81-9D-01-11-49 (#1c)
...[생략]...
19: 15-12-80-81-02-11-81-AD-11-49 (#726)
1a: 15-12-80-81-02-0E-02 (#826)

Assembly (0x20):
======================================================================================================
   Name                                     Version  Culture  PublicKey  Flags  HashAlgorithm
======================================================================================================
1: 'Microsoft.Metadata.Visualizer' (#10c7)  1.0.0.0  nil      nil        0      0x00008004 (Sha1)

AssemblyRef (0x23):
=======================================================================================================
   Name                                    Version   Culture  PublicKeyOrToken                Flags
=======================================================================================================
1: 'System.Runtime' (#780)                 4.1.0.0   nil      B0-3F-5F-7F-11-D5-0A-3A (#8c3)  0
2: 'System.IO' (#22a)                      4.1.0.0   nil      B0-3F-5F-7F-11-D5-0A-3A (#8c3)  0
3: 'System.Reflection.Metadata' (#236)     1.3.0.0   nil      B0-3F-5F-7F-11-D5-0A-3A (#8c3)  0
...[생략]...
a: 'System.Reflection.Primitives' (#13b2)  4.0.0.0   nil      B0-3F-5F-7F-11-D5-0A-3A (#8c3)  0
b: 'System.Console' (#74b)                 4.0.0.0   nil      B0-3F-5F-7F-11-D5-0A-3A (#8c3)  0

GenericParam (0x2a):
================================================================
   Name               Seq#  Attributes  TypeConstraints
================================================================
1: 'TEntity' (#17fa)  0     0           nil
2: 'T' (#234)         0     0           0x2c000001-0x2c000001
3: 'THandle' (#48b)   0     0           nil

MethodSpec (0x2b):
===============================================================
    Method                  Signature
===============================================================
 1: 0x0a000010 (MemberRef)  0A-01-12-3D (#53)
 2: 0x0a000015 (MemberRef)  0A-02-12-3D-15-11-45-01-11-49 (#b2)
 3: 0x0a000016 (MemberRef)  0A-01-15-11-45-01-11-49 (#ce)
 4: 0x0a00001a (MemberRef)  0A-01-12-3D (#53)
 5: 0x0a00001a (MemberRef)  0A-01-1D-0E (#106)
...[생략]...
13: 0x06000016 (MethodDef)  0A-01-11-81-AD (#731)
14: 0x0a00012c (MemberRef)  0A-01-0E (#842)
15: 0x0a000016 (MemberRef)  0A-01-11-49 (#1cd)

GenericParamConstraint (0x2c):
====================================================
   Parent                     Type
====================================================
1: 0x2a000002 (GenericParam)  0x1b000001 (TypeSpec)

#US (size = 2816):
  0: ''
  1: '>>>'
  9: '>>> Generation {0}:'
  31: '  '
  37: 'x'
  3b: ': '
...[생략]...
  af2: '''
  af6: '{'
  afa: '}'
  afe: ''
  aff: ''

#String (size = 6160):
  0: ''
  1: '<>9__20_0'
  b: '<Literal>b__20_0'
  1c: '<>c__DisplayClass0_0'
  31: '<>9__21_0'
  3b: '<Literal>b__21_0'
...[생략]...
  17cc: 'Any'
  17d0: 'EditAndContinueLogEntry'
  17e8: 'WriteDeclSecurity'
  17fa: 'TEntity'
  1802: 'WriteProperty'

#Blob (size = 2840):
  0:
  1: 20-01-01-08
  6: 20-00-01
  a: 20-01-01-11-11
  10: 20-01-01-0E
  15: 15-12-79-01-1E-00
  1c: 15-12-81-9D-01-11-49
  24: 07-02-02-15-12-4D-01-12-3D
...[생략]...
  afa: 01-00-07-31-2E-30-2E-30-2E-30-00-00
  b07: 01-00-05-31-2E-30-2E-30-00-00
  b12: 01-00-00-00
  b17:

#Guid (size = 16):
  1: {5592d697-bdc0-4859-aced-22e20a3efaee}




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







[최초 등록일: ]
[최종 수정일: 11/7/2023]

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

비밀번호

댓글 작성자
 



2020-08-01 10시46분
[이동우] 우연찮게 둘렀다가 잘보고갑니답!
[guest]

1  2  3  4  [5]  6  7  8  9  10  11  12  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13818정성태11/15/20245273Windows: 272. Windows 11 24H2 - sudo 추가
13817정성태11/14/20244929Linux: 106. eBPF / bpf2go - (BPF_MAP_TYPE_HASH) Map을 이용한 전역 변수 구현
13816정성태11/14/20245386닷넷: 2312. C#, C++ - Windows / Linux 환경의 Thread Name 설정파일 다운로드1
13815정성태11/13/20244809Linux: 105. eBPF - bpf2go에서 전역 변수 설정 방법
13814정성태11/13/20245283닷넷: 2311. C# - Windows / Linux 환경에서 Native Thread ID 가져오기파일 다운로드1
13813정성태11/12/20245032닷넷: 2310. .NET의 Rune 타입과 emoji 표현파일 다운로드1
13812정성태11/11/20245264오류 유형: 933. Active Directory - The forest functional level is not supported.
13811정성태11/11/20244848Linux: 104. Linux - COLUMNS 환경변수가 언제나 80으로 설정되는 환경
13810정성태11/10/20245374Linux: 103. eBPF (bpf2go) - Tracepoint를 이용한 트레이스 (BPF_PROG_TYPE_TRACEPOINT)
13809정성태11/10/20245261Windows: 271. 윈도우 서버 2025 마이그레이션
13808정성태11/9/20245257오류 유형: 932. Linux - 커널 업그레이드 후 "error: bad shim signature" 오류 발생
13807정성태11/9/20244994Linux: 102. Linux - 커널 이미지 파일 서명 (Ubuntu 환경)
13806정성태11/8/20244902Windows: 270. 어댑터 상세 정보(Network Connection Details) 창의 내용이 비어 있는 경우
13805정성태11/8/20244736오류 유형: 931. Active Directory의 adprep 또는 복제가 안 되는 경우
13804정성태11/7/20245366Linux: 101. eBPF 함수의 인자를 다루는 방법
13803정성태11/7/20245319닷넷: 2309. C# - .NET Core에서 바뀐 DateTime.Ticks의 정밀도
13802정성태11/6/20245702Windows: 269. GetSystemTimeAsFileTime과 GetSystemTimePreciseAsFileTime의 차이점파일 다운로드1
13801정성태11/5/20245481Linux: 100. eBPF의 2가지 방식 - libbcc와 libbpf(CO-RE)
13800정성태11/3/20246321닷넷: 2308. C# - ICU 라이브러리를 활용한 문자열의 대소문자 변환 [2]파일 다운로드1
13799정성태11/2/20244907개발 환경 구성: 732. 모바일 웹 브라우저에서 유니코드 문자가 표시되지 않는 경우
13798정성태11/2/20245505개발 환경 구성: 731. 유니코드 - 출력 예시 및 폰트 찾기
13797정성태11/1/20245493C/C++: 185. C++ - 문자열의 대소문자를 변환하는 transform + std::tolower/toupper 방식의 문제점파일 다운로드1
13796정성태10/31/20245382C/C++: 184. C++ - ICU dll을 이용하는 예제 코드 (Windows)파일 다운로드1
13795정성태10/31/20245164Windows: 268. Windows - 리눅스 환경처럼 공백으로 끝나는 프롬프트 만들기
13794정성태10/30/20245261닷넷: 2307. C# - 윈도우에서 한글(및 유니코드)을 포함한 콘솔 프로그램을 컴파일 및 실행하는 방법
13793정성태10/28/20245134C/C++: 183. C++ - 윈도우에서 한글(및 유니코드)을 포함한 콘솔 프로그램을 컴파일 및 실행하는 방법
1  2  3  4  [5]  6  7  8  9  10  11  12  13  14  15  ...