Поделиться через


Встроенные API, помеченные как RequiresDynamicCode

При обычных обстоятельствах вызов API-интерфейсов, аннотированных с RequiresDynamicCodeAttribute помощью приложения, опубликованного с помощью собственного AOT, активирует предупреждение IL3050 (избегайте вызова элементов, аннотированных с помощью "RequiresDynamicCodeAttribute" при публикации в качестве собственного AOT). API- интерфейсы, которые активируют предупреждение, могут неправильно вести себя после компиляции AOT.

Некоторые API-интерфейсы с аннотированием RequiresDynamicCode по-прежнему можно использовать без активации предупреждения при вызове в определенном шаблоне. При использовании в рамках шаблона вызов API может быть статически проанализирован компилятором, не создает предупреждение и ведет себя должным образом во время выполнения.

Метод Enum.GetValues(Type)

Вызовы этого API не вызывают предупреждение, если конкретный тип перечисления статически отображается в тексте вызывающего метода. Например, Enum.GetValues(typeof(AttributeTargets)) не активирует предупреждение, но Enum.GetValues(typeof(T)) и Enum.GetValues(someType) делает это.

Метод Marshal.DestroyStructure(IntPtr, Type)

Вызовы этого API не вызывают предупреждение, если конкретный тип статически отображается в тексте вызывающего метода. Например, Marshal.DestroyStructure(offs, typeof(bool)) не активирует предупреждение, но Marshal.DestroyStructure(offs, typeof(T)) и Marshal.DestroyStructure(offs, someType) делает это.

Метод Marshal.GetDelegateForFunctionPointer(IntPtr, Type)

Вызовы этого API не вызывают предупреждение, если конкретный тип статически отображается в тексте вызывающего метода. Например, Marshal.GetDelegateForFunctionPointer(ptr, typeof(bool)) не активирует предупреждение, но Marshal.GetDelegateForFunctionPointer(ptr, typeof(T)) и Marshal.GetDelegateForFunctionPointer(ptr, someType) делает это.

Метод Marshal.OffsetOf(Type, String)

Вызовы этого API не вызывают предупреждение, если конкретный тип статически отображается в тексте вызывающего метода. Например, Marshal.OffsetOf(typeof(Point), someField) не активирует предупреждение, но Marshal.OffsetOf(typeof(T), someField) и Marshal.OffsetOf(someType, someField) делает это.

Метод Marshal.PtrToStructure(IntPtr, Type)

Вызовы этого API не вызывают предупреждение, если конкретный тип статически отображается в тексте вызывающего метода. Например, Marshal.PtrToStructure(offs, typeof(bool)) не активирует предупреждение, но Marshal.PtrToStructure(offs, typeof(T)) и Marshal.PtrToStructure(offs, someType) делает это.

Метод Marshal.SizeOf(Type)

Вызовы этого API не вызывают предупреждение, если конкретный тип статически отображается в тексте вызывающего метода. Например, Marshal.SizeOf(typeof(bool)) не активирует предупреждение, но Marshal.SizeOf(typeof(T)) и Marshal.SizeOf(someType) делает это.

Метод MethodInfo.MakeGenericMethod(Type[]) (.NET 9+)

Вызовы этого API не вызывают предупреждение, если определение универсального метода и аргументы экземпляра статически видны в тексте вызывающего метода. Например, typeof(SomeType).GetMethod("GenericMethod").MakeGenericMethod(typeof(int)). В качестве аргумента также можно использовать универсальный параметр: typeof(SomeType).GetMethod("GenericMethod").MakeGenericMethod(typeof(T)) также не предупреждает.

Если определение универсального типа статически отображается в тексте вызывающего метода, а все универсальные параметры этого типа ограничены классом, вызов также не активирует предупреждение IL3050. В этом случае аргументы не должны быть статически видимыми. Например:

// No IL3050 warning on MakeGenericMethod because T is constrained to be class
typeof(SomeType).GetMethod("GenericMethod").MakeGenericMethod(Type.GetType(Console.ReadLine()));
class SomeType
{
    public void GenericMethod<T>() where T : class { }
}

Все остальные случаи, такие как someMethod.MakeGenericMethod(typeof(int)) или typeof(SomeType).GetMethod("GenericMethod").MakeGenericMethod(someType) где someType имеет неизвестное значение, активируют предупреждение.

Метод Type.MakeGenericType(Type[]) (.NET 9+)

Вызовы этого API не активируют предупреждение, если определение универсального типа и аргументы экземпляра статически видны в тексте вызывающего метода. Например, typeof(List<>).MakeGenericType(typeof(int)). В качестве аргумента также можно использовать универсальный параметр: typeof(List<>).MakeGenericType(typeof(T)) также не предупреждает.

Если определение универсального типа статически отображается в тексте вызывающего метода, а все универсальные параметры этого типа ограничены классом, вызов также не активирует предупреждение IL3050. В этом случае аргументы не должны быть статически видимыми. Например:

// No IL3050 warning on MakeGenericType because T is constrained to be class
typeof(Generic<>).MakeGenericType(Type.GetType(Console.ReadLine()));
class Generic<T> where T : class { }

Все остальные случаи, такие как someType.MakeGenericType(typeof(int)) или typeof(List<>).MakeGenericType(someType) где someType имеет неизвестное значение, активируют предупреждение.