Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Třída AssemblyLoadContext byla zavedena v .NET Core a není k dispozici v rozhraní .NET Framework. Tento článek doplňuje AssemblyLoadContext dokumentaci k rozhraní API koncepčními informacemi.
Tento článek je relevantní pro vývojáře, kteří implementuje dynamické načítání, zejména vývojáře architektury dynamického načítání.
Co je AssemblyLoadContext?
Každá aplikace .NET 5+ a .NET Core implicitně používá AssemblyLoadContext. Je to poskytovatel běhového prostředí pro načítání a vyhledání závislostí. Při každém načtení závislosti se vyvolá instance, AssemblyLoadContext která ji vyhledá.
- AssemblyLoadContext poskytuje službu vyhledání, načítání a ukládání spravovaných sestavení do mezipaměti a dalších závislostí.
- Aby bylo možné podporovat dynamické načítání a uvolňování kódu, vytvoří izolovaný kontext pro načítání kódu a jeho závislostí ve vlastní AssemblyLoadContext instanci.
Pravidla správy verzí
Jedna AssemblyLoadContext instance je omezena na načtení přesně jedné verze Assembly na každý jednoduchý název sestavení. Pokud je odkaz na sestavení vyřešen proti AssemblyLoadContext instanci, která již má sestavení tohoto názvu načteno, je požadovaná verze porovnána s načtenou verzí. Řešení bude úspěšné pouze v případě, že načtená verze je stejná nebo vyšší než požadovaná verze.
Kdy potřebujete více instancí AssemblyLoadContext?
Omezení, že jedna AssemblyLoadContext instance může načíst pouze jednu verzi sestavení, může být problém při dynamickém načítání modulů kódu. Každý modul je nezávisle kompilován a moduly mohou záviset na různých verzích Assembly. To je často problém, když různé moduly závisí na různých verzích běžně používané knihovny.
Pro podporu dynamického načítání kódu AssemblyLoadContext poskytuje rozhraní API pro načítání konfliktních verzí ve Assembly stejné aplikaci. Každá AssemblyLoadContext instance poskytuje jedinečný slovník, který mapuje každý AssemblyName.Name na konkrétní instanci Assembly.
Poskytuje také pohodlný mechanismus pro seskupování závislostí souvisejících s modulem kódu pro pozdější uvolnění.
Instance AssemblyLoadContext.Default
Instance AssemblyLoadContext.Default se při spuštění automaticky naplní modulem runtime. Používá výchozí sondování k nalezení a určení všech statických závislostí.
Řeší nejběžnější scénáře načítání závislostí.
Dynamické závislosti
AssemblyLoadContext obsahuje různé události a virtuální funkce, které je možné přepsat.
Instance AssemblyLoadContext.Default podporuje pouze přepisování událostí.
Články Spravovaný algoritmus načítání sestavení, Satelitní algoritmus načítání sestavení a Nespravovaný (nativní) algoritmus načítání knihovny se týkají všech dostupných událostí a virtuálních funkcí. Články zobrazují relativní pozici každé události a funkce v algoritmech načítání. Tento článek tyto informace nereprodukuje.
Tato část se zabývá obecnými principy relevantních událostí a funkcí.
- Opakovatelné. Dotaz na konkrétní závislost musí vždy vést ke stejné odpovědi. Musí se vrátit stejná načtená instance závislostí. Tento požadavek je zásadní pro konzistenci mezipaměti. Zejména pro spravovaná sestavení vytváříme Assembly mezipaměť. Klíč mezipaměti je jednoduchý název sestavení, AssemblyName.Name.
-
Obvykle neházíme. Očekává se, že tyto funkce vrátí hodnotu
nullnamísto vyhození výjimky, když nelze najít požadovanou závislost. Vyvolání předčasně ukončí vyhledávání a rozšíří výjimku volajícímu. Vyvolání by mělo být omezeno na neočekávané chyby, jako je poškozené sestavení nebo nedostatek paměti. - Vyhněte se rekurzi. Mějte na paměti, že tyto funkce a obslužné rutiny implementují pravidla načítání pro vyhledání závislostí. Vaše implementace by neměla volat rozhraní API, která aktivují rekurzi. Váš kód by obvykle měl volat načítací funkci AssemblyLoadContext, která vyžaduje konkrétní cestu nebo referenční argument paměti.
-
Načtěte do správného AssemblyLoadContextu. Volba místa, kde se mají načítat závislosti, je specifická pro aplikaci. Volba je implementována těmito událostmi a funkcemi. Když váš kód volá funkce typu 'load-by-path' AssemblyLoadContext, měly by být volány v instanci, ve které chcete kód načíst. Někdy může být nejjednodušší možností vrátit se
nulla nechat AssemblyLoadContext.Default zvládnout zatížení. - Mějte na paměti závody vláken. Načítání může být aktivováno více vlákny. AssemblyLoadContext řeší závody mezi vlákny atomickým přidáním sestavení do své mezipaměti. Instance poraženého v závodě je zahozena. V logice implementace nepřidávejte další logiku, která nezpracuje více vláken správně.
Jak jsou dynamické závislosti izolované?
Každá AssemblyLoadContext instance představuje jedinečný obor pro Assembly instance a Type definice.
Mezi těmito závislostmi neexistuje žádná binární izolace. Jsou izolované jenom tím, že se navzájem nenajdou podle jména.
V každém AssemblyLoadContextz nich:
- AssemblyName.Name může odkazovat na jinou Assembly instanci.
-
Type.GetType může vrátit jinou instanci typu pro stejný typ
name.
Sdílené závislosti
Závislosti je možné snadno sdílet mezi AssemblyLoadContext instancemi. Obecný model je určený k tomu, aby AssemblyLoadContext načetl závislost. Druhá strana sdílí závislost tím, že používá odkaz na načtené sestavení.
Toto sdílení je vyžadováno pro sestavení modulu runtime. Tato sestavení lze načíst pouze do AssemblyLoadContext.Defaultsouboru . Totéž se vyžaduje pro frameworky, jako je ASP.NET, WPF nebo WinForms.
Doporučuje se načíst sdílené závislosti do AssemblyLoadContext.Defaultsouboru . Toto sdílení je běžným vzorem návrhu.
Sdílení se implementuje v kódování vlastní AssemblyLoadContext instance. AssemblyLoadContext obsahuje různé události a virtuální funkce, které je možné přepsat. Pokud některé z těchto funkcí vrátí odkaz na instanci Assembly, která byla načtena v jiné instanci AssemblyLoadContext, potom je instance Assembly sdílena. Standardní algoritmus nahrávání odkazuje na AssemblyLoadContext.Default pro nahrávání, aby zjednodušil běžný způsob sdílení. Další informace naleznete v tématu Algoritmus načítání spravovaných sestavení.
Problémy s převodem typu
Pokud dvě AssemblyLoadContext instance obsahují definice typu se stejným nametypem, nejedná se o stejný typ. Jsou stejného typu, pokud a pouze pokud pocházejí ze stejné Assembly instance.
Komplikací je, že výjimkové zprávy o těchto neshodných typech mohou být matoucí. Typy jsou odkazovány ve zprávách o výjimce jejich jednoduchými názvy typů. Běžná zpráva o výjimce v tomto případě je ve formuláři:
Objekt typu 'IsolatedType' nelze převést na typ 'IsolatedType'.
Ladění problémů s převodem typů
Vzhledem k páru neodpovídajících typů je důležité vědět také:
- Každý typ Type.Assemblyje .
- Každý typ AssemblyLoadContext, který lze získat prostřednictvím funkce AssemblyLoadContext.GetLoadContext(Assembly).
Vzhledem k dvěma objektům a a bvyhodnocení následujících hodnot v ladicím programu bude užitečné:
// In debugger look at each assembly's instance, Location, and FullName
a.GetType().Assembly
b.GetType().Assembly
// In debugger look at each AssemblyLoadContext's instance and name
System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(a.GetType().Assembly)
System.Runtime.Loader.AssemblyLoadContext.GetLoadContext(b.GetType().Assembly)
Řešení problémů s převodem typů
Existují dva vzory návrhu pro řešení těchto problémů s převodem typů.
Používejte běžné sdílené typy. Tento sdílený typ může být buď primitivním typem modulu runtime, nebo může zahrnovat vytvoření nového sdíleného typu ve sdíleném sestavení. Sdílený typ je často rozhraní definované v sestavení aplikace. Další informace najdete v tématu o sdílení závislostí.
Pomocí technik seřazování můžete převést z jednoho typu na jiný.