web-dev-qa-db-ja.com

__DynamicallyInvokable属性の目的は何ですか?

見渡す System.Linq.Enumerable DotPeekで、いくつかのメソッドには[__DynamicallyInvokable]属性。

この属性はどのような役割を果たしますか? DotPeekによって追加されたものですか、それとも別の役割を果たしていますか?おそらく、メソッドを最適化する最適な方法をコンパイラーに通知していますか?

169
Jamie Dixon

文書化されていませんが、.NET 4.5の最適化の1つのように見えます。これは、リフレクションタイプ情報キャッシュを準備するために使用され、一般的なフレームワークタイプでの後続のリフレクションコードの実行を高速化するために使用されるようです。 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しか考えられません。

131
Hans Passant

内部メソッドのRuntime*Info.IsNonW8PFrameworkAPI()スイートで使用されていることがわかりました。この属性をメンバーに設定すると、IsNonW8PFrameworkAPI()がfalseを返すため、WinRTアプリケーションでメンバーが利用可能になり、The API '...' cannot be used on the current platform.例外。

プロファイラーの作成者は、WinRTでアクセスしたい場合、プロファイラーによってフレームワークアセンブリに発行されたメンバーにこの属性を配置する必要があります。

23
Stefan Dragnev