리플렉션을 사용하는 API

경우에 따라 코드에서 리플렉션 사용이 명확하지 않으므로 .NET 네이티브 도구 체인은 런타임에 필요한 메타데이터를 보존하지 않습니다. 이 항목은 리플렉션 API의 일부로는 간주되지 않지만 리플렉션을 사용해야 정상적으로 실행되는 몇 가지 일반적인 API 또는 프로그래밍 패턴에 대해 설명합니다. 소스 코드에서 이러한 API를 사용하는 경우, API에 대한 정보를 런타임 지시문(.rd.xml) 파일에 추가하여 해당 API 호출 시 런타임에 MissingMetadataException 예외 또는 일부 기타 예외가 발생하지 않도록 할 수 있습니다.

Type.MakeGenericType 메서드

다음과 같은 코드를 사용해 Type.MakeGenericType 메서드를 호출하여 제네릭 형식 AppClass<T>을(를) 동적으로 인스턴스화할 수 있습니다.

var t = Type.GetType("App1.AppClass`1", true);
Type[] typeArgs = {typeof(int)};
Type t2 = t.MakeGenericType(typeArgs);
Activator.CreateInstance(t2);

이 코드가 런타임에 정상적으로 실행되려면 여러 메타데이터 항목이 필요합니다. 그 중 첫 번째는 인스턴스화되지 않은 제네릭 형식 AppClass<T>에 대한 Browse 메타데이터입니다.

<Type Name="App1.AppClass`1" Browse="Required PublicAndInternal" />

이 메타데이터가 있으면 Type.GetType(String, Boolean) 메서드가 정상적으로 호출되며 유효한 Type 개체가 반환됩니다.

그러나 인스턴스화되지 않은 제네릭 형식에 대한 메타데이터를 추가하더라도 Type.MakeGenericType 메서드를 호출하면 MissingMetadataException 예외가 throw됩니다.

다음의 형식에 대한 메타데이터가 성능상의 이유로 제거되었으므로 이 작업을 수행할 수 없습니다.

App1.AppClass`1<System.Int32>.

다음 런타임 지시문을 런타임 지시문 파일에 추가하여 AppClass<T>을(를) 통한 System.Int32의 특정 인스턴스화에 대해 Activate 메타데이터를 추가할 수 있습니다.

<TypeInstantiation Name="App1.AppClass" Arguments="System.Int32"
                   Activate="Required Public" />

AppClass<T>을(를) 통한 각 인스턴스화에서는 별도의 지시문이 필요합니다(Type.MakeGenericType 메서드를 사용하여 작성되며 정적으로 사용되지 않는 경우).

MethodInfo.MakeGenericMethod 메서드

Class1 클래스에 제네릭 메서드 GetMethod<T>(T t), GetMethod이(가) 포함되어 있는 경우 다음과 같은 코드를 사용하여 리플렉션을 통해 호출될 수 있습니다.

Type ct = typeof(Class1);
MethodInfo mi = ct.GetMethod("GetMethod");
Type[] typeArgs = {typeof(int)};
object[] parameters = { 12 };
var method = mi.MakeGenericMethod(typeArgs);
Class1 c = new Class1();
method.Invoke(c, parameters);

이 코드를 정상적으로 실행하려면 다음과 같은 여러 메타데이터 항목이 필요합니다.

  • 해당 메서드를 호출할 형식에 대한 Browse 메타데이터입니다.

  • 호출하려는 메서드에 대한 Browse 메타데이터입니다. 공용 메서드의 경우 포함 형식에 대한 공용 Browse 메타데이터를 추가하면 메서드도 포함됩니다.

  • 리플렉션 호출 대리자가 .NET 네이티브 도구 체인에서 제거되지 않도록 호출하려는 메서드에 대한 동적 메타데이터입니다. 메서드에 대한 동적 메타데이터가 누락되면 MethodInfo.MakeGenericMethod 메서드 호출 시 다음의 예외가 throw됩니다.

    MakeGenericMethod() cannot create this generic method instantiation because the instantiation was not metadata-enabled: 'App1.Class1.GenMethod<Int32>(Int32)'.
    

다음의 런타임 지시문을 사용하면 필요한 모든 메타데이터를 사용할 수 있습니다.

<Type Name="App1.Class1" Browse="Required PublicAndInternal">
   <MethodInstantiation Name="GenMethod" Arguments="System.Int32" Dynamic="Required"/>
</Type>

MethodInstantiation 지시문은 동적으로 호출되는 메서드의 서로 다른 각 인스턴스화에 필요하며, Arguments 요소는 각 인스턴스화 인수를 반영하기 위해 업데이트됩니다.

Array.CreateInstance 및 Type.MakeTypeArray 메서드

다음의 예시는 Class1 형식에 대해 Type.MakeArrayTypeArray.CreateInstance 메서드를 호출합니다.

Type t = typeof(Class1);
Type at = t.MakeArrayType(1);
Array arr = Array.CreateInstance(at, 10);

배열 메타데이터가 없으면 다음의 오류가 발생합니다.

This operation cannot be carried out as metadata for the following type was removed for performance reasons:

App1.Class1[]

Unfortunately, no further information is available.

배열 형식을 동적으로 인스턴스화하려면 해당 형식에 대한 Browse 메타데이터가 필요합니다. 다음의 런타임 지시문을 사용하면 Class1[]을(를) 동적으로 인스턴스화할 수 있습니다.

<Type Name="App1.Class1[]" Browse="Required Public" />

참고 항목