Thuộc tính __DOUNDallyInvokable để làm gì?


181

Nhìn qua System.Linq.Enumerabletrong DotPeek tôi nhận thấy rằng một số phương thức có hương vị với một [__DynamicallyInvokable]thuộc tính.

Thuộc tính này đóng vai trò gì? Đây có phải là thứ được thêm bởi DotPeek hay nó đóng vai trò khác, có lẽ thông báo cho trình biên dịch về cách tốt nhất để tối ưu hóa các phương thức?


2
String.Empty cũng có cái này, btw.
Marc Gravell

1
Cũng vậy IReadOnlyCollection<T>.
Drew Noakes

1
System.ServiceModel v3's BasicHttpBinding.TextEncoding(mà trong V4 đã chuyển đến một lớp cơ sở mới và trở thành HttpBindingBase.TextEncoding)
Ruben Bartelink

nó cũng được sử dụng cho các giá trị số nguyên trong các
enum

một khi tôi gặp trường hợp khi phương thức với thuộc tính này được nội tuyến trong tập hợp được tạo (DateTime.AddYears, .Net 4.5)
gdbdable

Câu trả lời:


139

Nó không có giấy tờ, nhưng có vẻ như là một trong những tối ưu hóa trong .NET 4.5. Nó dường như được sử dụng để đánh dấu bộ đệm thông tin loại phản chiếu, làm cho mã phản chiếu tiếp theo trên các loại khung chung chạy nhanh hơn. Có một nhận xét về nó trong Nguồn tham chiếu cho thuộc tính System.Reflection.Ass lanh.cs, RuntimeAss lanh.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;
 }

Không có gợi ý thêm về "API may mắn" có nghĩa là gì. Mặc dù rõ ràng từ bối cảnh rằng điều này sẽ chỉ hoạt động trên các loại trong chính khung. Phải có thêm mã ở đâu đó để kiểm tra thuộc tính được áp dụng cho các kiểu và phương thức. Không biết vị trí của nó nằm ở đâu, nhưng cho rằng nó sẽ cần phải có chế độ xem tất cả các loại .NET để có bộ nhớ đệm, tôi chỉ có thể nghĩ về Ngen.exe.


7
Có vẻ như giá trị được lưu trữ đang được sử dụng để kiểm tra xem API có khả dụng trên WP8 hay không.
usr

1
+1 Xem nhận xét của tôi về Q của OP - một trường hợp trong đó CLR dường như đang thực hiện mánh khóe dựa trên điều này là trong việc xử lý các phương thức 'nhẹ' (ví dụ: giảm một cấp lên lớp cơ sở mới) dưới sự thống nhất
Ruben Bartelink

2
Đó là thủ thuật [TypeForwardTo], một thứ hoàn toàn khác.
Hans Passant

@HansPassant Thú vị - nghe có vẻ như tôi có thể sai nên ... đã không nghĩ đến việc kiểm tra lắp ráp / loại ban đầu. Tóm lại là trên 4,5 trích dẫn bất động sản (không phải loại) đã chuyển tương đối so với nơi nó được trên 3,5 (về mặt kỹ thuật, System.ServiceModel 3.0). Tôi đã giả định rằng việc hợp nhất một mscorlibtài liệu tham khảo la đang diễn ra nhưng có rất nhiều vấn đề xoay quanh vấn đề cụ thể của tôi dù sao đi nữa - sẽ báo cáo lại và / hoặc xóa bất kỳ âm điệu gây hiểu lầm nào cho các bình luận của tôi trong khóa học do ...
Ruben Bartelink

1
@HansPassant Từ nghiên cứu sâu hơn ... Không thể thấy bất cứ điều gì Loại Chuyển tiếp đang làm những thứ khác ngoài Loại chuyển tiếp vì vậy tại thời điểm này tôi xin khác biệt với một thứ hoàn toàn khác . Các lực lượng tại nơi làm việc chỉ đơn giản là khi bạn có tham chiếu lắp ráp CLR2 System.ServiceModel v3, tải nó dưới bản nâng cấp tự động CLR4 tới System.ServiceModel v4. Điều thú vị là .NET 4.5 thực hiện cập nhật tại chỗ cho các bit System.ServiceModelthả trong lớp cơ sở mới bên dưới và di chuyển thuộc tính xuống một mức .
Ruben Bartelink

23

Tôi thấy rằng nó được sử dụng trong Runtime*Info.IsNonW8PFrameworkAPI()bộ phương pháp nội bộ. Việc đặt thuộc tính này vào thành viên sẽ khiến IsNonW8PFrameworkAPI () trả về falsecho nó và do đó làm cho thành viên có sẵn trong các ứng dụng WinRT và tắt The API '...' cannot be used on the current platform.ngoại lệ.

Người viết Profiler nên đặt thuộc tính này cho các thành viên được trình phát bởi trình lược tả của họ thành các cụm khung, nếu họ muốn truy cập chúng dưới WinRT.


1
Vâng, mã được tìm thấy bởi @Hans thiết lập các cờ tìm kiếm RuntimeAssembly.InvocableAttributeCtorToken, được gọi bằng các IsNonW8PFrameworkAPI()phương thức bạn đề cập.
Đánh dấu
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.