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

(시리즈 글이 4개 있습니다.)
.NET Framework: 784. C# - 제네릭 인자를 가진 타입을 생성하는 방법
; https://www.sysnet.pe.kr/2/0/11582

.NET Framework: 787. object로 형변환된 인스턴스를 원래의 타입 인자로 제네릭 메서드를 호출하는 방법
; https://www.sysnet.pe.kr/2/0/11589

닷넷: 2145. C# - 제네릭의 형식 매개변수에 속한 (매개변수를 가진) 생성자를 호출하는 방법
; https://www.sysnet.pe.kr/2/0/13417

닷넷: 2251. C# - 제네릭 인자를 가진 타입을 생성하는 방법 - 두 번째 이야기
; https://www.sysnet.pe.kr/2/0/13610




C# - 제네릭 인자를 가진 타입을 생성하는 방법 - 두 번째 이야기

예를 들어, 다음과 같은 C# 코드가 있을 때,

ValueTuple<int, int, int> value = new(5, 6, 7);

저 value에 대해서 Reflection으로 5, 6, 7 값을 가져오고 싶다면 어떻게 해야 할까요?

우선, ValueTuple<T1, T2, T3>에 대한 타입 정보를 가져와야 하는데요, C# 코드에서 사용하듯이 이렇게 하시면,

Type stateType = typeof(AppDomain).Assembly.GetType("System.ValueTuple<int, int, int>");

// 또는,

Type stateType = typeof(AppDomain).Assembly.GetType("System.ValueTuple<T1, T2, T3>");

타입 정보를 찾을 수 없습니다. 이런 경우 특별한 표기법을 이용해야 하는데요, backtick(`)을 이용해 제네릭 인자 수를 기입하는 식이어야 합니다.

Type stateType = typeof(AppDomain).Assembly.GetType("System.ValueTuple`3");

위의 경우 제네릭 인자의 타입을 지정하지 않았는데요, 물론 지정하는 것도 가능합니다. 그리고 이 이름은 다음과 같은 식으로 구하는 것도 가능합니다.

ValueTuple<int, int, int> value = new(5, 6, 7);
Console.WriteLine(value.GetType().FullName);
// 출력 결과:
// System.ValueTuple`3[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

제네릭 인자의 타입으로 int에 대한 FullName이 기록되고 있는데, 이것은 다음과 같이 줄이는 것도 가능합니다.

Type stateType = typeof(AppDomain).Assembly.GetType("System.ValueTuple`3[[System.Int32],[System.Int32],[System.Int32]]");

일단, 위와 같이 제네릭 인자의 타입까지 지정했다면 다음과 같이 해당 타입의 필드를 역시 Reflection으로 가져올 수 있습니다.

{
    var fi = stateType.GetField("Item1");
    Console.WriteLine(fi.GetValue(value)); // 출력 결과: 5
}




여기서 주의할 것은, 제네릭 인자를 지정하지 않은 경우에는 GetField로 값을 가져올 수 없다는 점입니다.

ValueTuple<int, int, int> value = new(5, 6, 7);

Type stateType = typeof(AppDomain).Assembly.GetType("System.ValueTuple`3");

var fi = stateType.GetField("Item1");
Console.WriteLine(fi.GetValue(value)); // 예외 발생
/*
Unhandled Exception: System.InvalidOperationException: Late bound operations cannot be performed on fields with types for which Type.ContainsGenericParameters is true.
   at System.Reflection.RtFieldInfo.InternalGetValue(Object obj, StackCrawlMark& stackMark)
   at System.Reflection.RtFieldInfo.GetValue(Object obj)
   at ConsoleApp2.Program.Main(String[] args)
*/

위의 오류를 고치는 방법은, 1) 이전에 설명한 것처럼 제네릭 인자를 명시해 GetType을 호출하든가, 2) 아니면 MakeGenericType을 이용해 제네릭 인자의 타입 정보를 명시해 구한 그 타입을 다시 사용해야 합니다.

ValueTuple<int, int, int> value = new(5, 6, 7);

Type stateType = typeof(AppDomain).Assembly.GetType("System.ValueTuple`3");
stateType = stateType.MakeGenericType(typeof(int), typeof(int), typeof(int));

var fi = stateType.GetField("Item1");
Console.WriteLine(fi.GetValue(value)); // 출력 결과: 5

2가지 방법의 장단점이 있는데요, 첫 번째 방법은 제네릭 인자의 타입을 정의한 어셈블리를 참조해야만 하는 반면, 두 번째 방법은 참조 없이도 그 타입 조차도 Reflection으로 접근해 MakeGenericType의 인자로 넘겨줄 수 있습니다.




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







[최초 등록일: ]
[최종 수정일: 4/28/2024]

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

비밀번호

댓글 작성자
 




... 106  107  108  109  110  111  112  113  114  115  116  [117]  118  119  120  ...
NoWriterDateCnt.TitleFile(s)
11106정성태11/8/201630369.NET Framework: 623. C# - PeerFinder를 이용한 Wi-Fi Direct 데이터 통신 예제 [2]파일 다운로드1
11105정성태11/8/201625736.NET Framework: 622. PeerFinder Wi-Fi Direct 통신 시 Read/Write/Dispose 문제
11104정성태11/8/201623766개발 환경 구성: 305. PeerFinder로 Wi-Fi Direct 연결 시 방화벽 문제
11103정성태11/8/201624851오류 유형: 370. PeerFinder.ConnectAsync의 결과 값인 Task.Result를 호출할 때 System.AggregateException 예외 발생
11102정성태11/8/201625223오류 유형: 369. PeerFinder.FindAllPeersAsync 호출 시 System.UnauthorizedAccessException 예외 발생
11101정성태11/8/201626367.NET Framework: 621. 닷넷 프로파일러의 오류 코드 - 0x80131363
11100정성태11/7/201635076개발 환경 구성: 304. Wi-Fi Direct 지원 여부 확인 방법 [1]
11099정성태11/7/201636580.NET Framework: 620. C#에서 C/C++ 함수로 콜백 함수를 전달하는 예제 코드파일 다운로드1
11098정성태11/7/201625931오류 유형: 368. 빌드 이벤트에서 robocopy 사용 시 $(TargetDir) 매크로를 지정하는 경우 오류 발생
11097정성태11/7/201628149오류 유형: 367. go install: no install location for directory [...경로...] outside GOPATH
11096정성태11/6/201631184디버깅 기술: 83. PDB 파일을 수동으로 다운로드하는 방법
11095정성태11/6/201628913.NET Framework: 619. C# - Cognitive Services 중의 하나인 Face API를 사용해 얼굴 인식 및 흐림(blur) 효과 적용 [1]파일 다운로드1
11094정성태11/5/201629850VC++: 105. Visual Studio 2013/2015 - Ceemple OpenCV 확장을 이용한 웹캠 영상 출력
11093정성태11/4/201630178웹: 34. Edge 브라우저도 지원하는 클립보드 복사를 위한 자바스크립트 코드
11092정성태11/3/201637555.NET Framework: 618. C# - NAudio를 이용한 MP3 파일 재생 [5]파일 다운로드1
11091정성태11/3/201629926VC++: 104. std::call_once를 이용해 thread-safe한 Singleton 객체 생성파일 다운로드1
11090정성태11/1/201631550VC++: 103. C++ CreateTimerQueue, CreateTimerQueueTimer 예제 코드 [9]파일 다운로드1
11089정성태11/1/201632483디버깅 기술: 82. Windows 10을 위한 Symbol(PDB) 파일 내려받는 방법 [2]
11088정성태11/1/201634222.NET Framework: 617. C# - AForge.NET을 이용한 MP4 동영상 파일 재생 [7]파일 다운로드1
11087정성태11/1/201628753.NET Framework: 616. AForge.Video.FFMPEG를 최신 버전의 ffmpeg 파일로 의존성을 변경하는 방법파일 다운로드1
11086정성태11/1/201623385오류 유형: 366. The Microsoft Passport Container service terminated with the following error: General access denied error
11085정성태10/27/201638823.NET Framework: 615. C# - AForge.NET을 이용한 웹캠 영상 출력 [2]파일 다운로드1
11084정성태10/26/201626373오류 유형: 365. The User Profile Service service failed to the sign-in.
11083정성태10/26/201632901Windows: 131. 윈도우 10에서 사라진 "Adapters and Bindings" 네트워크 우선 순위 조정 기능 [1]
11082정성태10/26/201636162.NET Framework: 614. C# - DateTime.Ticks의 정밀도 [4]파일 다운로드1
11081정성태10/26/201625140오류 유형: 364. You need to fix your Microsoft Account for apps on your other devices to be able to launch apps and continue experiences on this device.
... 106  107  108  109  110  111  112  113  114  115  116  [117]  118  119  120  ...