แอตทริบิวต์ __DynamicallyInvokable คืออะไร


181

มองผ่านSystem.Linq.EnumerableDotPeek ฉันสังเกตว่าวิธีการบางอย่างมีการแต่งกลิ่นด้วย[__DynamicallyInvokable]คุณลักษณะ

คุณลักษณะนี้มีบทบาทอะไร? มันเป็นสิ่งที่เพิ่มโดย DotPeek หรือมันมีบทบาทอื่นอาจแจ้งให้คอมไพเลอร์ทราบถึงวิธีการที่ดีที่สุดในการปรับแต่งวิธีการให้ดีที่สุด?


2
String.Empty ยังมีสิ่งนี้ btw
Marc Gravell

1
ก็IReadOnlyCollection<T>เช่นกัน
Drew Noakes

1
และSystem.ServiceModel v3's BasicHttpBinding.TextEncoding(ซึ่งใน V4 ได้ขยับขึ้นไปที่ชั้นฐานใหม่และกลายเป็นHttpBindingBase.TextEncoding)
Ruben Bartelink

มันยังใช้สำหรับค่าจำนวนเต็มใน System enums เช่น DayOfWeek
beauXjames

เมื่อฉันมีกรณีเมื่อวิธีการที่มีคุณลักษณะนี้ถูก inlined ในการสร้างที่สร้างขึ้น (DateTime.AddYears, .Net 4.5)
gdbdable

คำตอบ:


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
ดูเหมือนว่ามีการใช้ค่าที่เก็บไว้เพื่อตรวจสอบว่า API นั้นมีอยู่ใน WP8 หรือไม่
usr

1
+1 ดูความคิดเห็นของฉันเกี่ยวกับ OP ของ Q - กรณีหนึ่งที่ CLR ดูเหมือนว่าจะใช้กลอุบายในการจัดการวิธีการ 'เล็กน้อย' (เช่นลงหนึ่งระดับสู่คลาสฐานใหม่) ภายใต้การรวมกลุ่ม
Ruben Bartelink

2
นั่นคือเคล็ดลับ [TypeForwardTo] สิ่งที่แตกต่างอย่างสิ้นเชิง
Hans Passant

@HansPassant Interesting - ดูเหมือนว่าฉันอาจผิดไปแล้ว ... ไม่เคยคิดที่จะตรวจสอบชุดประกอบ / ประเภทดั้งเดิม บรรทัดล่างคือเมื่อวันที่ 4.5 ทรัพย์สินที่อ้างถึง(ไม่ใช่ประเภท) ได้ย้ายเทียบกับที่มันอยู่ใน 3.5 (ในทางเทคนิคSystem.ServiceModel 3.0) ฉันได้สันนิษฐานว่าการmscorlibอ้างอิงla เป็นการเล่น แต่มีจำนวนมากวนรอบกลับในปัญหาเฉพาะของฉันที่จะทำต่อไป - จะรายงานกลับและ / หรือเอาน้ำเสียงที่ทำให้เข้าใจผิดใด ๆ ความคิดเห็นของฉันในหลักสูตรเนื่องจาก ...
Ruben Bartelink

1
@HansPassant จากการวิจัยเพิ่มเติม ... ไม่เห็นอะไรเลยอีกต่อไป Type Forwarding กำลังทำสิ่งอื่นนอกเหนือจาก Forwarding Types ดังนั้น ณ จุดนี้ฉันขอให้แตกต่างกับสิ่งที่ต่างออกไปเล็กน้อย กองกำลังที่ทำงานเป็นเพียงว่าเมื่อคุณมี 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.ข้อยกเว้น

ผู้เขียน Profiler ควรวางแอ็ตทริบิวต์นี้ไว้บนสมาชิกที่ปล่อยออกมาจาก profiler ลงในแอสเซมบลีเฟรมเวิร์กหากพวกเขาต้องการเข้าถึงพวกเขาภายใต้ WinRT


1
ใช่รหัสที่ค้นพบโดย @Hans จะตั้งค่าสถานะRuntimeAssembly.InvocableAttributeCtorTokenที่ค้นหาซึ่งเรียกโดยIsNonW8PFrameworkAPI()วิธีการที่คุณพูดถึง
Mark Hurd
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.