198

Looking through System.Linq.Enumerable in DotPeek I notice that some methods are flavoured with a [__DynamicallyInvokable] attribute.

What role does this attribute play? Is it something added by DotPeek or does it play another role, perhaps informing the compiler on how best to optimise the methods?

Jamie Dixon
  • 53,019
  • 19
  • 125
  • 162

3 Answers3

151

It is undocumented, but it looks like one of the optimizations in .NET 4.5. It appears to be used to prime the reflection type info cache, making subsequent reflection code on common framework types run faster. There's a comment about it in the Reference Source for System.Reflection.Assembly.cs, RuntimeAssembly.Flags property:

 // 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;
 }

Without further hints what a "blessed API" might mean. Although it is clear from the context that this will only work on types in the framework itself. There ought to be additional code somewhere that checks the attribute applied to types and methods. No idea where that is located, but given that it would have to need to have a view of all .NET types to have a shot at caching, I can only think of Ngen.exe.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 9
    It looks like the stored value is being used to check if the API is available on WP8. – usr Oct 10 '12 at 10:32
  • 1
    +1 See my comment on the OP's Q - one case where the CLR seems to be doing trickery based on this is in the handling 'slight' moves of methods (e.g. down one level onto a new base class) under unification – Ruben Bartelink Feb 13 '13 at 13:29
  • 4
    That's the [TypeForwardTo] trick, something completely different. – Hans Passant Feb 13 '13 at 13:53
  • @HansPassant Interesting - sounds like I may well be wrong so... hadn't thought of examining the original assembly/type. Bottom line is that on 4.5 the cited *property* (not the type) has moved relative to where it was on 3.5 (technically, `System.ServiceModel 3.0`). I had assumed that unification a la `mscorlib` references was at play but have plenty some circling back around on my specific issue to do anyway - will report back and/or remove any misleading tone to my comments in due course... – Ruben Bartelink Feb 13 '13 at 23:15
  • 1
    @HansPassant From further research... Cant see anything re Type Forwarding doing stuff other than Forwarding Types so at this point I beg to differ with the *something completely different* bit. The forces at work are simply that when you have a CLR2 assembly referencing `System.ServiceModel v3`, loading it under CLR4 auto-upgrades to `System.ServiceModel v4`. The fun bit is that .NET 4.5 does an in place update to the bits of `System.ServiceModel` dropping in a new base class underneath **and moves the property down a level**. – Ruben Bartelink Feb 14 '13 at 10:36
  • It remains my contention that the presence of the attribute has a part to play in enabling this redirection to be [relatively] transparently managed. NB the attribute is borne on both the property itself and the individual property getter and property setter. NB `GetMethods()` only shows it in the new location, regardless of the supportedRuntime of the exe or the dll in which I have my logic. – Ruben Bartelink Feb 14 '13 at 10:47
  • It can be defined in nay assembly, and it's looked up by name >> This "__DynamicallyInvokableAttribute" is a type defined in its own assembly. https://pp.vk.me/c636518/v636518918/cb1b/8KCUadKSipE.jpg – Bogdan Mart May 31 '16 at 20:56
  • Here is a link to the reference source: http://referencesource.microsoft.com/#mscorlib/system/reflection/assembly.cs,1247 – Vladimir Reshetnikov Nov 23 '17 at 16:54
27

I found that it's used in the Runtime*Info.IsNonW8PFrameworkAPI() suite of internal methods. Having this attribute placed on a member makes IsNonW8PFrameworkAPI() return false for it and thus makes the member available in WinRT applications and shuts up the The API '...' cannot be used on the current platform. exception.

Profiler writers should place this attribute on members emitted by their profiler into framework assemblies, if they want to access them under WinRT.

Stefan Dragnev
  • 14,143
  • 6
  • 48
  • 52
  • 2
    Yeah, the code found by @Hans sets up the flags looked for by `RuntimeAssembly.InvocableAttributeCtorToken`, which is called by the `IsNonW8PFrameworkAPI()` methods you mention. – Mark Hurd Aug 08 '16 at 14:56
0

sorry if I answer late. This attribute is used to call unmanaged code function from managed code. It is used to separate the managed language from the unmanaged language. a barrier of two worlds. It is also used for security reasons. to make unmanaged code reflection inaccessible.