__DynamicallyInvokable özniteliği ne için?


181

System.Linq.EnumerableDotPeek bakarak bazı yöntemlerin bir [__DynamicallyInvokable]öznitelik ile aromalı olduğunu fark ettim .

Bu özellik hangi rolü oynar? DotPeek tarafından eklenen bir şey mi yoksa başka bir rol oynuyor mu, belki de derleyiciye yöntemleri en iyi nasıl optimize edebileceği konusunda bilgi veriyor mu?


2
String.Empty'de buna sahip, btw.
Marc Gravell

1
Aynen öyle IReadOnlyCollection<T>.
Drew Noakes

1
Ve System.ServiceModel v3's BasicHttpBinding.TextEncoding( HttpBindingBase.TextEncoding
V4'te

DayOfWeek gibi sistem numaralarındaki tamsayı değerleri için de kullanılır
beauXjames

bir kez ben bu özniteliğe sahip yöntem oluşturulan derleme (DateTime.AddYears, .Net 4.5)
gdbdable

Yanıtlar:


139

Belgelenmemiş, ancak .NET 4.5'teki optimizasyonlardan birine benziyor. Yansıtma türü bilgi önbelleğini hazırlamak için kullanılır, bu da ortak çerçeve türlerinde sonraki yansıma kodunun daha hızlı çalışmasını sağlar. Bu konuda System.Reflection.Assembly.cs, RuntimeAssembly.Flags özelliğinde Reference Source içinde bir yorum var:

 // 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;
 }

Başka ipuçları olmadan bir "kutsanmış API" ne anlama gelebilir. Bağlamdan anlaşılacağı gibi, bunun yalnızca çerçevenin kendisindeki türler üzerinde çalışacağı açıktır. Türlere ve yöntemlere uygulanan özniteliği kontrol eden bir yerde ek kod bulunmalıdır. Nerede olduğunu bilmiyorum, ama önbellek bir çekim için tüm .NET türleri bir görünüm olması gerekir göz önüne alındığında, ben sadece Ngen.exe düşünebilirsiniz.


7
Depolanan değerin, API'nin WP8'de kullanılabilir olup olmadığını kontrol etmek için kullanıldığı anlaşılıyor.
usr

1
+1 OP'nin Q - CLR'nin buna dayanarak hile yaptığı bir durum hakkındaki
yorumuma bakın,

2
Bu [TypeForwardTo] hilesi, tamamen farklı bir şey.
Hans Passant

@HansPassant İlginç - yanlış olabilirim gibi geliyor yani orijinal montajı / türü incelemeyi düşünmemiştim. Alt satırda, 4.5'te belirtilen özellik (tür değil) 3.5'teki yere göre (teknik olarak System.ServiceModel 3.0) taşınmıştır . Ben bir la mscorlibreferanslar birleşme oyunda olduğunu varsayalım ama yine de yapmak için benim belirli bir konu etrafında etrafında dönen bazı bol var - geri bildirmek ve / veya zaman içinde benim yorum yanıltıcı tonu kaldırır ...
Ruben Bartelink

1
@HansPassant Daha fazla araştırmadan ... Cant Yönlendirme Türleri dışında Yönlendirme türlerinden başka bir şey göremiyorum bu yüzden bu noktada tamamen farklı bir şeyle farklı olmaya yalvarıyorum . İşyerindeki güçler, bir CLR2 montajına başvurduğunuzda System.ServiceModel v3, onu CLR4 otomatik yükseltmeleri altında yüklemektir System.ServiceModel v4. Eğlenceli bit, .NET System.ServiceModel4.5'in altında yeni bir temel sınıfta bırakma bitleri için yerinde bir güncelleme yapması ve özelliği bir seviyeye taşımasıdır .
Ruben Bartelink

23

Runtime*Info.IsNonW8PFrameworkAPI()İç yöntemler paketinde kullanıldığını gördüm . Bu özelliğin bir üyeye yerleştirilmesi, IsNonW8PFrameworkAPI () öğesini geri döndürür falseve böylece üyeyi WinRT uygulamalarında kullanılabilir hale getirir ve The API '...' cannot be used on the current platform.istisnayı kapatır .

Profil oluşturucu yazarlar, bu özelliği profil oluşturucuları tarafından yayılan üyelere WinRT altında erişmek istiyorlarsa çerçeve derlemelerine yerleştirmelidir.


1
Evet, @Hans tarafından bulunan kod RuntimeAssembly.InvocableAttributeCtorToken, IsNonW8PFrameworkAPI()bahsettiğiniz yöntemlerle çağrılan bayrakları arar .
Mark Hurd
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.