web-dev-qa-db-fra.com

A quoi sert l'attribut __DynamicallyInvokable?

En regardant à travers System.Linq.Enumerable dans DotPeek, je remarque que certaines méthodes sont aromatisées avec un [__DynamicallyInvokable] attribut.

Quel rôle joue cet attribut? Est-ce quelque chose ajouté par DotPeek ou joue-t-il un autre rôle, en informant peut-être le compilateur de la meilleure façon d'optimiser les méthodes?

169
Jamie Dixon

C'est non documenté, mais cela ressemble à l'une des optimisations de .NET 4.5. Il semble être utilisé pour amorcer le cache d'informations de type de réflexion, accélérant ainsi l'exécution du code de réflexion sur les types de structure courants. Il y a un commentaire à ce sujet dans la source de référence pour la propriété 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;
 }

Sans autres indications, ce qu'une "API bénie" pourrait signifier. Bien que le contexte l'indique clairement, cela ne fonctionnera que sur les types du cadre lui-même. Il devrait y avoir du code supplémentaire quelque part qui vérifie l'attribut appliqué aux types et aux méthodes. Aucune idée de l'endroit où cela se trouve, mais étant donné qu'il aurait besoin d'avoir une vue de tous les types .NET pour avoir une chance de mettre en cache, je ne peux que penser à Ngen.exe.

131
Hans Passant

J'ai trouvé qu'il est utilisé dans la suite de méthodes internes Runtime*Info.IsNonW8PFrameworkAPI(). Si cet attribut est placé sur un membre, IsNonW8PFrameworkAPI () renvoie false pour lui et rend ainsi le membre disponible dans les applications WinRT et ferme le The API '...' cannot be used on the current platform. exception.

Les rédacteurs de profileur doivent placer cet attribut sur les membres émis par leur profileur dans des assemblys d'infrastructure s'ils souhaitent y accéder sous WinRT.

23
Stefan Dragnev