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