Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 1개 있습니다.)

GetFunctionPointer 호출 시 System.InvalidProgramException 예외 발생

현상은 간단합니다. 제네릭 메서드인 경우 그에 대해 GetFunctionPointer를 호출하면,

using System;
using System.Reflection;
using System.Threading;

public class Program
{
    public static void GenericMethod<T>(T obj)
    {
        Thread.Sleep(1);
    }

    static unsafe void Main()
    {
        Type type = typeof(Program);
        MethodInfo mi = type.GetMethod("GenericMethod", BindingFlags.Static | BindingFlags.Public);
        {
            string fullName = string.Format("{0}.{1}", type.FullName, mi.Name);
            IntPtr methodBody = mi.MethodHandle.GetFunctionPointer(); // 예외 발생
            Console.WriteLine(fullName);
        }
    }
}

MethodInfo.MethodHandle.GetFunctionPointer 메서드 호출에서 다음과 같은 예외가 발생합니다.

An unhandled exception of type 'System.InvalidProgramException' occurred in mscorlib.dll

Additional information: Common Language Runtime detected an invalid program.

이게... 이상한 듯 하면서도 사실 당연한 겁니다. 왜냐하면, 제네릭인 경우 컴파일러가 생성한 IL 단계에는 제네릭의 타입이 정해지지 않은 상태이고, 실제 메서드가 사용될 때 기계어 컴파일이 타입에 따라 확장되면서 컴파일되기 때문에 GenericMethod 자체의 FunctionPointer 값을 대표할 수 없는 것입니다. 가령 그 값이 0x00100으로 반환되었다고 해도 GenericMethod<int>(int obj)로 확장된 메서드의 FunctionPointer는 또 다른 값이 될 수 있는 것입니다.

그래서, 원래는 제네릭 메서드의 제대로 된 FunctionPointer를 구하고 싶다면 다음과 같이 해줘야 합니다.

MethodInfo mi = type.GetMethod("GenericMethod", BindingFlags.Static | BindingFlags.Public);
MethodInfo intMethod = mi.MakeGenericMethod(typeof(int));

string fullName = string.Format("{0}.{1}", type.FullName, intMethod.Name);
IntPtr methodBody = intMethod.MethodHandle.GetFunctionPointer();
Console.WriteLine(fullName); // Program.GenericMethod

그런데, 재미있는 것은 클래스 수준의 제네릭 인자가 있는 것은 또 잘됩니다.

public class GenericClass<T>
{
    public static void Test(T arg)
    {
        Console.WriteLine(arg);
    }
}

type = typeof(GenericClass<>);
mi = type.GetMethod("Test", BindingFlags.Static | BindingFlags.Public);
{
    string fullName = string.Format("{0}.{1}", type.FullName, mi.Name);
    IntPtr methodBody = mi.MethodHandle.GetFunctionPointer();
    Console.WriteLine(fullName); // GenericClass`1.Test
}




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

[연관 글]






[최초 등록일: ]
[최종 수정일: 7/17/2021]

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

비밀번호

댓글 작성자
 




... 166  167  168  [169]  170  171  172  173  174  175  176  177  178  179  180  ...
NoWriterDateCnt.TitleFile(s)
908정성태8/17/201028116개발 환경 구성: 82. Windows Virtual PC의 네트워크 유형 (3)
907정성태8/14/201025570개발 환경 구성: 81. Windows Virtual PC의 네트워크 유형 (2)
906정성태8/13/201033251개발 환경 구성: 80. Windows Virtual PC의 네트워크 유형 (1)
905정성태8/8/201037356Team Foundation Server: 39. 배치 파일로 팀 빌드 구성 [2]파일 다운로드1
904정성태8/8/201039559오류 유형: 101. SignTool Error: No certificates were found that met all the given criteria. [2]
903정성태8/6/201036510Team Foundation Server: 38. TFS 소스 코드 관리 기능 (4) - Branch
902정성태8/5/201028916Team Foundation Server: 37. TFS 2010의 소스 서버 수작업 구성
901정성태8/4/201028118Team Foundation Server: 36. TFS 소스 코드 관리 기능 (3) - Label
900정성태8/3/201031040Team Foundation Server: 35. TFS 소스 코드 관리 기능 (2) - Shelveset
899정성태8/2/201032583Team Foundation Server: 34. TFS 소스 코드 관리 기능 (1) - Changeset
898정성태7/31/201032739.NET Framework: 182. WCF의 InactivityTimeout [1]파일 다운로드1
897정성태7/26/201133701.NET Framework: 181. AssemblyVersion, AssemblyFileVersion, AssemblyInformationalVersion [4]
896정성태7/25/201040756.NET Framework: 180. C# Singleton 인스턴스 생성 [2]
895정성태7/25/201024431VS.NET IDE: 68. Visual Studio 2010 - .NET 1.1 원격 디버깅
894정성태7/25/201030363오류 유형: 100. Could not find the Database Engine startup handle. [1]
893정성태7/25/201031286오류 유형: 99. .NET 4.0 설치된 윈도우 7에서 SQL Server 2008 R2 설치 오류
892정성태7/9/201032433오류 유형: 98. 영문 윈도우에 한글 SQL Server 2008 R2 설치할 때 오류 [4]
891정성태7/8/201028901오류 유형: 97. MsiGetProductInfo failed to retrieve ProductVersion for package with Product Code = '{...}'. Error code: 1605. [2]
889정성태7/5/201030754.NET Framework: 179. Dictionary.Get(A) 대신 Dictionary.Get(A.GetHashCode())를 사용해서는 안 되는 이유 [1]
888정성태6/30/201028332오류 유형: 96. Hyper-V 연결 오류 - A connection will not be made because credentials may not be sent to the remote computer
887정성태6/23/201038208개발 환경 구성: 79. Hyper-V의 가상 머신에서 소리 재생 방법 [2]
886정성태6/23/201026168제니퍼 .NET: 14. ASMX, WCF 호출 모니터링 및 누수 확인
885정성태6/20/201028083개발 환경 구성: 78. COM+ 서버에서 COM+ 서버를 호출하는 방법
884정성태6/20/201030793제니퍼 .NET: 13. COM+ 서버 모니터링 [2]
883정성태6/18/201032764개발 환경 구성: 77. Appinit_Dlls로 구현한 환경 변수 설정 DLL [5]파일 다운로드1
882정성태6/17/201035748개발 환경 구성: 76. JKS(Java Key Store)에 저장된 인증서를 ActiveX 코드 서명에 사용하는 방법 [1]
... 166  167  168  [169]  170  171  172  173  174  175  176  177  178  179  180  ...