__DynamicallyInvokable属性的作用是什么?


181

综观System.Linq.Enumerable在DotPeek我注意到,有些方法是调味用[__DynamicallyInvokable]的属性。

此属性起什么作用?它是DotPeek补充的,还是扮演另一个角色,也许可以通知编译器如何最佳地优化方法?


2
String.Empty也有这个,顺便说一句。
马克·格雷夫

1
也是IReadOnlyCollection<T>
德鲁·诺阿克斯

1
System.ServiceModel v3BasicHttpBinding.TextEncoding(其在V4已经移动到一个新的基类和变HttpBindingBase.TextEncoding
鲁Bartelink

它也用于系统枚举(如DayOfWeek)中的整数值
beauXjames,2014年

有一次我有一种情况,当在生成的程序集中内联具有此属性的方法时(DateTime.AddYears,.Net 4.5)
gdbdable 2015年

Answers:


139

它没有记录,但看起来像.NET 4.5中的优化之一。它似乎用于启动反射类型信息高速缓存,从而使常见框架类型上的后续反射代码运行得更快。在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。


7
似乎已使用存储的值来检查WP8上是否提供了API。
usr

1
+1请参阅我对OP的Q的评论-一种情况是CLR似乎在此方面做
trick俩,是

2
那是[TypeForwardTo]的把戏,完全不同。
汉斯·帕桑

@HansPassant有趣-听起来我可能是错的,所以...没想到要检查原始的程序集/类型。底线是在4.5上引用的属性(不是类型)相对于在3.5上的位置(技术上为System.ServiceModel 3.0)移动。我以为统一mscorlib参考文献正在发挥作用,但无论如何我都会
回避

1
@HansPassant来自进一步的研究...不能看到任何有关类型转发的内容,除了转发类型以外,所以在这一点上我希望与完全不同的内容有所不同。工作的力量很简单,当您引用CLR2程序集时System.ServiceModel v3,将其加载到CLR4自动升级到的状态下System.ServiceModel v4。有趣的一点是,.NET 4.5对就位System.ServiceModel的新位进行了原位更新,并将属性下移了一层
Ruben Bartelink

23

我发现它在Runtime*Info.IsNonW8PFrameworkAPI()内部方法套件中使用。将这个属性放在成员上会使IsNonW8PFrameworkAPI()返回false它,从而使该成员在WinRT应用程序中可用并关闭The API '...' cannot be used on the current platform.异常。

如果他们想在WinRT下访问它们,则Profiler编写者应将此属性放在其Profiler发出的成员中,这些成员由Profiler发送到框架程序集中。


1
是的,@ Hans找到的代码设置了所查找的标志RuntimeAssembly.InvocableAttributeCtorTokenIsNonW8PFrameworkAPI()您所提到的方法将调用该标志。
马克·赫德
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.