AOT uyarılarına giriş

Uygulamanızı Yerel AOT olarak yayımlarken, derleme işlemi çalışma zamanında uygulamayı desteklemek için gereken tüm yerel kodu ve veri yapılarını oluşturur. Bu, uygulamayı soyut terimlerle (sanal makine için bir program) açıklayan biçimlerden yürüten ve çalışma zamanında isteğe bağlı yerel gösterimler oluşturan yerel olmayan dağıtımlardan farklıdır.

Program bölümlerinin soyut gösterimlerinde yerel gösterime bire bir eşleme yoktur. Örneğin, genel List<T>.Add yöntemin soyut açıklaması, verilen T için özelleştirilmesi gereken sonsuz olabilecek yerel yöntem gövdelerine eşler (örneğin, List<int>.Add ve List<double>.Add).

Soyut kodun yerel kodla ilişkisi bire bir olmadığından, derleme işleminin derleme zamanında yerel kod gövdelerinin ve veri yapılarının tam bir listesini oluşturması gerekir. Bazı .NET API'leri için derleme zamanında bu listeyi oluşturmak zor olabilir. API, derleme zamanında beklenmeyen bir şekilde kullanılırsa, çalışma zamanında bir özel durum oluşturulur.

Yerel AOT olarak dağıtılırken davranış değişikliklerini önlemek için .NET SDK, "AOT uyarıları" aracılığıyla AOT uyumluluğunun statik analizini sağlar. Derleme, AOT ile uyumlu olmayabilecek kodu bulduğunda AOT uyarıları oluşturulur. AOT uyumlu olmayan kod, Yerel AOT olarak derlendikten sonra bir uygulamada davranış değişiklikleri ve hatta kilitlenmeler bile üretebilir. İdeal olan, Yerel AOT kullanan tüm uygulamalarda AOT uyarısı olmamasıdır. AOT uyarısı varsa Yerel AOT olarak derledikten sonra uygulamanızı kapsamlı bir şekilde test ederek davranış değişikliği olmadığından emin olun.

AOT uyarısı örnekleri

Çoğu C# kodu için, hangi yerel kodun oluşturulması gerektiğini belirlemek kolaydır. Yerel derleyici, yöntem gövdelerine yürüyebilir ve hangi yerel kod ve veri yapılarının erişilir olduğunu bulabilir. Ne yazık ki yansıma gibi bazı özellikler önemli bir sorun oluşturur. Aşağıdaki kodu inceleyin:

Type t = typeof(int);
while (true)
{
    t = typeof(GenericType<>).MakeGenericType(t);
    Console.WriteLine(Activator.CreateInstance(t));
}

struct GenericType<T> { }

Yukarıdaki program çok kullanışlı olmasa da, uygulamayı Yerel AOT olarak oluştururken sonsuz sayıda genel türün oluşturulmasını gerektiren aşırı bir durumu temsil eder. Yerel AOT olmadan, program belleği tükenene kadar çalışır. Yerel AOT ile, gerekli tüm türleri (sonsuz sayıda) oluştursaydık bile derlemek mümkün olmazdı.

Bu durumda, Yerel AOT derlemesi satırda aşağıdaki uyarıyı yayınlar MakeGenericType :

AOT analysis warning IL3050: Program.<Main>$(String[]): Using member 'System.Type.MakeGenericType(Type[])' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime.

Çalışma zamanında, uygulama gerçekten çağrıdan MakeGenericType bir özel durum oluşturur.

AOT uyarılarına tepki verme

AOT uyarıları, Yerel AOT derlemelerine öngörülebilirlik getirme amacını taşımaya yöneliktir. AOT uyarılarının çoğu, senaryoyu desteklemek için yerel kodun oluşturulmamış olduğu durumlarda olası çalışma zamanı özel durumuyla ilgilidir. En geniş kategori: RequiresDynamicCodeAttribute.

DynamicCode gerektirir

RequiresDynamicCodeAttribute basit ve geniştir: Bu, üyeye AOT ile uyumsuz olarak açıklama eklendiği anlamına gelen bir özniteliktir. Bu ek açıklama, üyenin çalışma zamanında yeni yerel kod oluşturmak için yansıma veya başka bir mekanizma kullanabileceği anlamına gelir. Bu öznitelik, kod temel olarak AOT uyumlu olmadığında veya yerel bağımlılık derleme zamanında statik olarak tahmin etmek için çok karmaşık olduğunda kullanılır. Bu genellikle API, yansıma yayma veya diğer çalışma zamanı kod oluşturma teknolojilerini kullanan Type.MakeGenericType yöntemler için geçerlidir. Aşağıdaki kodda bir örneği gösterilmiştir.

[RequiresDynamicCode("Use 'MethodFriendlyToAot' instead")]
void MethodWithReflectionEmit() { ... }

void TestMethod()
{
    // IL3050: Using method 'MethodWithReflectionEmit' which has 'RequiresDynamicCodeAttribute'
    // can break functionality when AOT compiling. Use 'MethodFriendlyToAot' instead.
    MethodWithReflectionEmit();
}

için RequiresDynamicCodeçok fazla geçici çözüm yoktur. En iyi düzeltme, Yerel AOT olarak oluştururken yöntemini çağırmaktan kaçınmak ve AOT uyumlu başka bir şey kullanmaktır. Bir kitaplık yazıyorsanız ve yöntemi çağırıp çağırmamak sizin denetiminizde değilse, kendi yönteminize de ekleyebilirsiniz RequiresDynamicCode . Bu, yönteminize AOT uyumlu olmadığı için ek açıklama ekler. Ek RequiresDynamicCode açıklamalı yöntemde tüm AOT uyarılarını sessize alır, ancak başka biri her çağırsa bir uyarı oluşturur. Bu nedenle, kitaplık yazarlarının uyarıyı genel API'ye "baloncukla" göndermesi çoğunlukla yararlıdır.

Bir şekilde çağrının güvenli olduğunu saptayabiliyorsanız ve tüm yerel kod çalışma zamanında kullanılabilir olacaksa, kullanarak UnconditionalSuppressMessageAttributeuyarıyı da gizleyebilirsiniz. Örneğin:

[RequiresDynamicCode("Use 'MethodFriendlyToAot' instead")]
void MethodWithReflectionEmit() { ... }

[UnconditionalSuppressMessage("Aot", "IL3050:RequiresDynamicCode",
    Justification = "The unfriendly method is not reachable with AOT")]
void TestMethod()
{
    If (RuntimeFeature.IsDynamicCodeSupported)
        MethodWithReflectionEmit(); // warning suppressed
}

UnconditionalSuppressMessage gibi SuppressMessage ancak ve diğer derleme sonrası araçlar tarafından publish görülebilir. SuppressMessage ve #pragma yönergeleri yalnızca kaynakta bulunur, bu nedenle derlemedeki uyarıları susturmak için kullanılamazlar.

Dikkat

AOT uyarılarını bastırırken dikkatli olun. Arama artık AOT uyumlu olabilir, ancak kodunuzu güncelleştirdikçe bu değişebilir ve tüm gizlemeleri gözden geçirmeyi unutabilirsiniz.