Что такое атрибут __DynamicallyInvokable?

Просматривая System.Linq.Enumerable в DotPeek, я замечаю, что некоторые методы приправлены атрибутом [__DynamicallyInvokable].

Какую роль играет этот атрибут? Это что-то добавленное DotPeek или оно играет другую роль, возможно, информируя компилятор о том, как лучше всего оптимизировать методы?

Ответ 1

Недокументирован, но он похож на одну из оптимизаций в .NET 4.5. По-видимому, он используется для заполнения кеша информации типа отражения, что делает следующий код отражения для общих типов фреймов более быстрым. Там есть комментарий об этом в источнике Reference Source для System.Reflection.Assembly.cs, RuntimeAssembly.Flags:

 // Each blessed API will be annotated with a "__DynamicallyInvokableAttribute".
 // This "__DynamicallyInvokableAttribute" is a type defined in its own assembly.
 // So the ctor is always a MethodDef and the type a TypeDef.
 // We cache this ctor MethodDef token for faster custom attribute lookup.
 // If this attribute type doesn't exist in the assembly, it means the assembly
 // doesn't contain any blessed APIs.
 Type invocableAttribute = GetType("__DynamicallyInvokableAttribute", false);
 if (invocableAttribute != null)
 {
     Contract.Assert(((MetadataToken)invocableAttribute.MetadataToken).IsTypeDef);

     ConstructorInfo ctor = invocableAttribute.GetConstructor(Type.EmptyTypes);
     Contract.Assert(ctor != null);

     int token = ctor.MetadataToken;
     Contract.Assert(((MetadataToken)token).IsMethodDef);

     flags |= (ASSEMBLY_FLAGS)token & ASSEMBLY_FLAGS.ASSEMBLY_FLAGS_TOKEN_MASK;
 }

Без дальнейших намеков, что может означать "благословенный API". Хотя из контекста ясно, что это будет работать только по типам самой структуры. Там должен быть дополнительный код, который проверяет атрибут, применяемый к типам и методам. Не знаю, где это расположено, но при условии, что для того, чтобы иметь возможность видеть все типы .NET, нужно иметь представление о кешировании, я могу только думать о Ngen.exe.

Ответ 2

Я обнаружил, что он используется в наборе внутренних методов Runtime*Info.IsNonW8PFrameworkAPI(). Наличие этого атрибута, помещенного в член, делает IsNonW8PFrameworkAPI() return false для него и, таким образом, делает член доступным в приложениях WinRT и закрывает исключение The API '...' cannot be used on the current platform..

Писатели-профилировщики должны поместить этот атрибут в члены, выпущенные их профилировщиком, в сборках фреймов, если они хотят получить к ним доступ в WinRT.