.NET 9.0'da yeni [26]: Dinamik montajların kalıcılığı geri döner

Womanne

Member
Modern .NET'te, infaz sırasında üretilen montaj şimdiye kadar sadece RAM'de tutulmuştur. .NET 9.0 ile, klasik .NET çerçevesinde olduğu gibi, dosya sisteminde Assiemi'nin yürütülmesi sırasında devam etmek artık mümkündür.






Dotnet Doctor-Holger Schwichtenberg




Holger Schwichtenberg, 53 ünlü uzmanla tavsiye ve eğitim yoluyla ve yazılımın geliştirilmesinde çok sayıda orta ve büyük şirketi destekleyen uzmanlar ağının teknik direktörüdür. Çok sayıda ulusal ve uluslararası uzman konferansındaki görünümleri, 90'dan fazla uzman kitabı ve 1.500'den fazla uzman makalesi sayesinde Holger Schwichtenberg, Almanya'daki .NET ve Web teknikleri için en iyi uzmanlardan biridir.







.NET 9.0 Önizleme 1'de Microsoft, dosya sisteminde veya herhangi bir akışta dinamik olarak montajı sürdürmek için klasik .NET Framework tarafından bilinen olasılığı yeniden tanıtmıştı.



Ancak önizleme 3'te Microsoft API'yi tekrar değiştirdi: daha önce kullanılan sınıf yerine AssemblyBuilder

AssemblyBuilder ab = AssemblyBuilder.DefinePersistedAssembly(new AssemblyName("Math"), typeof(object).Assembly);

Şimdi yeni sınıfı kullanın PersistedAssemblyBuilder:

PersistedAssemblyBuilder ab = new PersistedAssemblyBuilder(new AssemblyName("Math"), typeof(object).Assembly);



Aşağıdaki kod yeni sınıfın kullanımını göstermektedir. Giriş noktası gibi meta verilerin adaptasyonuna ilişkin diğer örnekler notlarda mevcuttur.



using System.Reflection;
using System.Reflection.Emit;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using ITVisions;
using Microsoft.NET.HostModel.AppHost;

namespace NET9_Console.FCL90;
internal class FCL9_Reflection
{

/// <summary>
/// Im modernen .NET konnten zur Laufzeit erzeugte Assemblies
/// bisher nur im RAM gehalten werden. Mit .NET 9.0 ist es mit
/// PersistedAssemblyBuilder nun auch wieder möglich, zur Laufzeit
/// erzeugte Assemblies im Dateisystem zu persistieren.
/// siehe auch https://stackoverflow.com/questions/78466316/unhandled-exception-system-io-filenotfoundexception-the-file-or-assembly-syst
/// </summary>
public void CreateAndSaveAssembly()
{
// TODO: Bei RTM-Version anpassen!
var currentVersion = "9.0.0";

CUI.Demo(nameof(CreateAndSaveAssembly));
string AssemblyName = "App42";
string AssemblyNameWithExtension = AssemblyName + ".exe";

CUI.H2($"nErzeuge {AssemblyNameWithExtension}");
string referencePath = @$"C:program FilesdotnetpacksMicrosoft.NETCore.App.Ref{currentVersion}refnet9.0";
PathAssemblyResolver resolver = new(Directory.GetFiles(referencePath, "*.dll"));
using MetadataLoadContext context = new(resolver);
Assembly coreAssembly = context.CoreAssembly!;
Type voidType = coreAssembly.GetType(typeof(void).FullName!)!;
Type objectType = coreAssembly.GetType(typeof(object).FullName!)!;
Type stringType = coreAssembly.GetType(typeof(string).FullName!)!;
Type int32Type = coreAssembly.GetType(typeof(Int32).FullName!)!;
Type stringArrayType = coreAssembly.GetType(typeof(string[]).FullName!)!;
Type consoleType = coreAssembly.GetType(typeof(Console).FullName!)!;

// --> NEU in .NET 9.0: PersistedAssemblyBuilder
// https://learn.microsoft.com/en-us/dotnet/api/system.reflection.emit.persistedassemblybuilder?view=net-9.0
PersistedAssemblyBuilder assemblyBuilder = new(new AssemblyName(AssemblyName), coreAssembly);

TypeBuilder typeBuilder = assemblyBuilder.DefineDynamicModule(AssemblyName).DefineType(AssemblyName, TypeAttributes.Public | TypeAttributes.Class, objectType);

#region Methode Sum() erzeugen
var mb = typeBuilder.DefineMethod("Sum", MethodAttributes.Public | MethodAttributes.Static,
int32Type, new Type[] { int32Type, int32Type });
var ilSum = mb.GetILGenerator();
ilSum.Emit(OpCodes.Ldarg_0);
ilSum.Emit(OpCodes.Ldarg_1);
ilSum.Emit(OpCodes.Add);
ilSum.Emit(OpCodes.Ret);
CUI.Cyan($"Sum() wurde erzeugt");
#endregion

#region Methode Main() erzeugen
MethodBuilder methodBuilder = typeBuilder.DefineMethod("Main", MethodAttributes.Public | MethodAttributes.Static, voidType, [stringArrayType]);
ILGenerator ilMain = methodBuilder.GetILGenerator();
// Aufruf von Console.WriteLine("Die Antwort auf Ihre Frage ist:")
ilMain.Emit(OpCodes.Ldstr, "Die Antwort auf Ihre Frage ist:");
ilMain.Emit(OpCodes.Call, consoleType.GetMethod("WriteLine", [stringType])!);
// Aufruf von Console.WriteLine(Sum(40,2))
ilMain.Emit(OpCodes.Ldc_I4, 40); // Load the constant 40
ilMain.Emit(OpCodes.Ldc_I4, 2); // Load the constant 2
ilMain.Emit(OpCodes.Call, mb);
var writeLineMethod = consoleType.GetMethod("WriteLine", [int32Type]);
ilMain.Emit(OpCodes.Call, writeLineMethod);
ilMain.Emit(OpCodes.Ret);
CUI.Cyan($"Main() wurde erzeugt");
#endregion

#region Metadaten und PE-Header erzeugen
typeBuilder.CreateType();

MetadataBuilder metadataBuilder = assemblyBuilder.GenerateMetadata(out BlobBuilder ilStream, out BlobBuilder fieldData);
PEHeaderBuilder peHeaderBuilder = new(imageCharacteristics: Characteristics.ExecutableImage);

ManagedPEBuilder peBuilder = new(
header: peHeaderBuilder,
metadataRootBuilder: new MetadataRootBuilder(metadataBuilder),
ilStream: ilStream,
mappedFieldData: fieldData,
entryPoint: MetadataTokens.MethodDefinitionHandle(methodBuilder.MetadataToken));
CUI.Cyan($"Metadaten und PE-Header wurden erzeugt");
#endregion

#region Speichern der DLL
BlobBuilder peBlob = new();
peBuilder.Serialize(peBlob);
using (FileStream fileStream = new($"{AssemblyName}.dll", FileMode.Create, FileAccess.Write))
{
peBlob.WriteContentTo(fileStream);
}
CUI.Cyan($"{AssemblyName}.dll wurde gespeichert");
#endregion

#region AppHost und runtimeconfig erzeugen
HostWriter.CreateAppHost(
@$"C:program FilesdotnetpacksMicrosoft.NETCore.App.Host.win-x64{currentVersion}runtimeswin-x64nativeapphost.exe",
$"{AssemblyName}.exe",
$"{AssemblyName}.dll");

CUI.Cyan($"{AssemblyName}.exe wurde gespeichert");

File.WriteAllText($"{AssemblyName}.runtimeconfig.json",
$$"""
{"runtimeOptions": {
"tfm": "net9.0",
"framework": {
"name": "Microsoft.NETCore.App",
"version": "{{currentVersion}}"
}
}
}
""");

CUI.Cyan($"{AssemblyName}.runtimeconfig.json wurde gespeichert");
#endregion

CUI.Success("OK");

#region Testen
CUI.H2($"nStarte {AssemblyName}.exe");
System.Diagnostics.Process.Start($"{AssemblyName}.exe");
#endregion
}
}





Örnek kodun sürümünün ekran görüntüsü



Kod, üretilirken bireysel pasajları yayar ve montajda devam eder.


(Resim: Ekran görüntüsü (Holger Schwichtenberg))




18 Kasım 2025'te BetterCode Online Konferansı () 10.0



(Resim: Coffeemill/123rf.com)


Sonraki LTS çıktısı devam ediyor: BetterCode Online Konferansı () .NET 10.0'da IX ve DPunkt.verlag tarafından düzenlenen 18 Kasım 2025'te IT-visions.de-Sesler Bu makalenin yazarı Dr. Holger Schwichtenberg ve diğer uzmanlar en önemli yenilikler. Bunlar.

Çevrimiçi mağazada indirimli kör kuş biletleri zaten mevcut olana kadar program henüz yayınlanmadı. Bir önceki yılın programı arşivde görüntülenebilir.








(RME)




Ne yazık ki, bu bağlantı artık geçerli değil.

Boşa harcanan eşyalara olan bağlantılar, 7 günlük daha büyükse veya çok sık çağrılmışsa gerçekleşmez.


Bu makaleyi okumak için bir Haberler+ paketine ihtiyacınız var. Şimdi yükümlülük olmadan bir hafta deneyin – yükümlülük olmadan!
 

Murat

New member
Modern .NET'te, infaz sırasında üretilen montaj şimdiye kadar sadece RAM'de tutulmuştur. .NET 9.0 ile, klasik .NET çerçevesinde olduğu gibi, dosya
Merhaba sohbete dahil olanlara

Katmanlı ve çok boyutlu bir konuyu böyle sade anlatmak gerçek uzmanlık göstergesi @Womanne

Şöyle bir detay daha var, aşağıdaki noktalar da işine yarayabilir

  • NET 9.0'da performans iyileştirmeleri çeşitli yollarla sağlanır
Bu kısmı da atlamamak lazım diye düşündüm
 

Erdemitlee

Global Mod
Global Mod
Modern .NET'te, infaz sırasında üretilen montaj şimdiye kadar sadece RAM'de tutulmuştur. .NET 9.0 ile, klasik .NET çerçevesinde olduğu gibi, dosya
Selam katılımcılar

Giriş bölümü bile merak uyandırıyor, sonuna kadar ilgiyle takip ettim @Womanne

Konuya ek olarak, aşağıdaki noktalar da işine yarayabilir

  • Daha fazla bilgi için Microsoft'un resmi .NET 9.0 sürüm notlarına başvurulabilir
Şöyle bir cümle daha yazayım dedim, umarım hoşuna gider

Murat' Alıntı:
Merhaba sohbete dahil olanlara Katmanlı ve çok boyutlu bir konuyu böyle sade anlatmak gerçek uzmanlık göstergesi @Womanne Şöyle bir detay daha var, aşağıdaki noktalar da işine yarayabilir NET 9.0'da performans
Buradaki teorik çerçeve oldukça sağlam @Murat, belli ki iyi araştırmışsın
 

Defne

New member
Modern .NET'te, infaz sırasında üretilen montaj şimdiye kadar sadece RAM'de tutulmuştur. .NET 9.0 ile, klasik .NET çerçevesinde olduğu gibi, dosya
Selam paylaşımcılar

Bilgiyle dolu ama bir yandan da anlaşılır kalmayı başaran nadir içeriklerden @Womanne

Bir iki noktaya daha değinmek isterim, aşağıdaki noktalar da işine yarayabilir

  • Bu iyileştirmeler, .NET 9.0'ın daha hızlı ve verimli bir şekilde çalışmasını mümkün kılar
Bazen tek bir cümle bile yetiyor, umarım burada öyle olur

Erdemitlee' Alıntı:
Selam katılımcılar Giriş bölümü bile merak uyandırıyor, sonuna kadar ilgiyle takip ettim @Womanne Konuya ek olarak, aşağıdaki noktalar da işine yarayabilir Daha fazla bilgi için Microsoft'un resmi .NET 9.0 sürüm
Bu bakış açını anlıyorum @Erdemitlee, fakat bazı yerlerde fazla kesin konuştuğunu düşünüyorum
 

GezginRuhlar

Global Mod
Global Mod
Modern .NET'te, infaz sırasında üretilen montaj şimdiye kadar sadece RAM'de tutulmuştur. .NET 9.0 ile, klasik .NET çerçevesinde olduğu gibi, dosya
Satır aralarındaki emek kendini hissettiriyor; detaylara verilen önem harika @Womanne

Bu arada şunu da söyleyeyim, aşağıdaki noktalar da işine yarayabilir

  • NET 9.0'da dinamik montajların kalıcılığının geri döndüğüne dair bir bilgi bulunmamaktadır. Ancak, .NET 9.0'da bazı yeni özellikler ve iyileştirmeler mevcuttur
Murat' Alıntı:
Merhaba sohbete dahil olanlara Katmanlı ve çok boyutlu bir konuyu böyle sade anlatmak gerçek uzmanlık göstergesi @Womanne Şöyle bir detay daha var, aşağıdaki noktalar da işine yarayabilir NET 9.0'da performans
İlginç bir ayrıntı yakalamışsın @Murat, ben böyle düşünmemiştim
 

Efe

New member
Modern .NET'te, infaz sırasında üretilen montaj şimdiye kadar sadece RAM'de tutulmuştur. .NET 9.0 ile, klasik .NET çerçevesinde olduğu gibi, dosya
Herkese selamlar

Yalın ama etkili anlatım tarzın metne çok şey katmış @Womanne

@Womanne, anlatımındaki sadelik ve netlik gerçekten etkileyici, emeğine sağlık

Biraz da ben dokunayım dedim, belki güzel tamamlar

Murat' Alıntı:
Merhaba sohbete dahil olanlara Katmanlı ve çok boyutlu bir konuyu böyle sade anlatmak gerçek uzmanlık göstergesi @Womanne Şöyle bir detay daha var, aşağıdaki noktalar da işine yarayabilir NET 9.0'da performans
Burada biraz cesur konuşmuşsun ama dayanak zayıf @Murat
 

Aksu

Global Mod
Global Mod
Modern .NET'te, infaz sırasında üretilen montaj şimdiye kadar sadece RAM'de tutulmuştur. .NET 9.0 ile, klasik .NET çerçevesinde olduğu gibi, dosya
Selam sevgili topluluk

Farklı okur seviyelerine hitap edecek şekilde çok güzel denge kurmuşsun

Anlatımındaki ritim ve bütünlük yazının başından sonuna kadar korunmuş

Konu dağılmasın diye sadece tek cümle bıraktım

Hiçbir otorite değilim ama kafam bu şekilde topladı

GezginRuhlar' Alıntı:
Satır aralarındaki emek kendini hissettiriyor; detaylara verilen önem harika @Womanne Bu arada şunu da söyleyeyim, aşağıdaki noktalar da işine yarayabilir NET 9.0'da dinamik
Katılmak zorundayım diyemem @GezginRuhlar, çünkü benim tecrübemde sonuçlar tamamen tersti

Efe' Alıntı:
Herkese selamlar Yalın ama etkili anlatım tarzın metne çok şey katmış @Womanne @Womanne, anlatımındaki sadelik ve netlik gerçekten etkileyici, emeğine sağlık Biraz da ben
Açıkçası söylediğin şey her durum için geçerli değil, özellikle bazı örneklerde tam tersi oluyor @Efe

Defne' Alıntı:
Selam paylaşımcılar Bilgiyle dolu ama bir yandan da anlaşılır kalmayı başaran nadir içeriklerden @Womanne Bir iki noktaya daha değinmek isterim, aşağıdaki noktalar da işine
Bu noktada biraz fazla genelleme yapmışsın gibi geliyor, yine de fikrine saygım var @Defne
 
Üst