What is the __DynamicallyInvokable attribute for?
Asked Answered
S

3

200

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?

Spare answered 23/9, 2012 at 8:12 Comment(5)
String.Empty also has this, btw.Undress
So does IReadOnlyCollection<T>.Coagulant
And System.ServiceModel v3's BasicHttpBinding.TextEncoding (which in V4 has moved up to a new base class and becomes HttpBindingBase.TextEncoding)Big
it is also used for the integer values in System enums like DayOfWeekHalftimbered
once i have a case when method with this attribute was inlined in generated assembly (DateTime.AddYears, .Net 4.5)Acetophenetidin
J
155

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.

Jennettejenni answered 23/9, 2012 at 11:44 Comment(8)
It looks like the stored value is being used to check if the API is available on WP8.Milburr
+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 unificationBig
That's the [TypeForwardTo] trick, something completely different.Jennettejenni
@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...Big
@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.Big
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.Big
It can be defined in nay assembly, and it's looked up by name >> This "__DynamicallyInvokableAttribute" is a type defined in its own assembly. pp.vk.me/c636518/v636518918/cb1b/8KCUadKSipE.jpgPrism
Here is a link to the reference source: referencesource.microsoft.com/#mscorlib/system/reflection/…Waddington
C
28

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.

Custodial answered 17/10, 2013 at 10:6 Comment(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.Impetus
Confirmed by the runtime team to be about the Windows Store: github.com/dotnet/runtime/issues/30809Plauen
H
-1

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.

Handbill answered 2/11, 2022 at 18:57 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.