Microsoft MVP성태의 닷넷 이야기
.NET Framework: 842. .NET Reflection을 대체할 System.Reflection.Metadata 소개 [링크 복사], [링크+제목 복사],
조회: 19781
글쓴 사람
정성태 (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]

... 76  77  78  79  80  81  82  83  84  85  86  87  88  [89]  90  ...
NoWriterDateCnt.TitleFile(s)
11707정성태9/30/201823804오류 유형: 489. ASP.NET Core를 docker에서 실행 시 "Failed with a critical error." 오류 발생 [1]
11706정성태9/29/201819998개발 환경 구성: 400. Synology NAS(DS216+II)에서 실행한 gcc의 Segmentation fault [2]
11705정성태9/29/201820813개발 환경 구성: 399. Synology NAS(DS216+II)에 gcc 컴파일러 설치
11704정성태9/29/201824854기타: 73. Synology NAS 신호음(beep) 끄기 [1]파일 다운로드1
11703정성태9/27/201819605개발 환경 구성: 398. Blazor 환경 구성 후 빌드 속도가 너무 느리다면? [2]
11702정성태9/26/201816810사물인터넷: 44. 넷두이노(Netduino)의 네트워크 설정 방법
11701정성태9/26/201822558개발 환경 구성: 397. 공유기를 일반 허브로 활용하는 방법파일 다운로드1
11700정성태9/21/201820645Graphics: 25. Unity - shader의 직교 투영(Orthographic projection) 행렬(UNITY_MATRIX_P)을 수작업으로 구성
11699정성태9/21/201819123오류 유형: 488. Add-AzureAccount 실행 시 "No subscriptions are associated with the logged in account in Azure Service Management (RDFE)." 오류
11698정성태9/21/201820277오류 유형: 487. 윈도우 성능 데이터를 원격 SQL에 저장하는 경우 "Call to SQLAllocConnect failed with %1." 오류 발생
11697정성태9/20/201819232Graphics: 24. Unity - unity_CameraWorldClipPlanes 내장 변수 의미
11696정성태9/19/201820155.NET Framework: 793. C# - REST API를 이용해 NuGet 저장소 제어파일 다운로드1
11695정성태9/19/201825279Graphics: 23. Unity - shader의 원근 투영(Perspective projection) 행렬(UNITY_MATRIX_P)을 수작업으로 구성
11694정성태9/17/201819527오류 유형: 486. nuget push 호출 시 405 Method Not Allowed 오류 발생
11693정성태9/16/201822693VS.NET IDE: 128. Unity - shader 코드 디버깅 방법
11692정성태9/13/201823024Graphics: 22. Unity - shader의 Camera matrix(UNITY_MATRIX_V)를 수작업으로 구성
11691정성태9/13/201819977VS.NET IDE: 127. Visual C++ / x64 환경에서 inline-assembly를 매크로 어셈블리로 대체하는 방법 - 두 번째 이야기
11690정성태9/13/201822928사물인터넷: 43. 555 타이머의 단안정 모드파일 다운로드1
11689정성태9/13/201822210VS.NET IDE: 126. 디컴파일된 소스에 탐색을 사용하도록 설정(Enable navigation to decompiled sources)
11688정성태9/11/201817542오류 유형: 485. iisreset - The data is invalid. (2147942413, 8007000d) 오류 발생
11687정성태9/11/201819435사물인터넷: 42. 사물인터넷 - 트랜지스터 다중 전압 테스트파일 다운로드1
11686정성태9/8/201818498사물인터넷: 41. 다중 전원의 소스를 가진 회로파일 다운로드1
11685정성태9/6/201818459사물인터넷: 40. 이어폰 소리를 capacitor로 필터링파일 다운로드1
11684정성태9/6/201821085개발 환경 구성: 396. pagefile.sys를 비활성화시켰는데도 working set 메모리가 줄어드는 이유파일 다운로드1
11683정성태9/5/201818692개발 환경 구성: 395. Azure Web App의 이벤트 로그를 확인하는 방법
11682정성태9/5/201817640오류 유형: 484. Fakes를 포함한 단위 테스트 프로젝트를 빌드 시 CS1729 관련 오류 발생
... 76  77  78  79  80  81  82  83  84  85  86  87  88  [89]  90  ...