Exportovat (0) Tisk
Rozbalit vše
Tento článek byl přeložen strojově počítačem. Původní text zobrazíte přesunutím ukazatele myši nad jednotlivé věty článku. Další informace
Překlad
Originál

Doporučené postupy pro načtení sestavení

Tento článek popisuje způsoby, jak se vyhnout problémům identity typů, jenž mohou vést k výjimkám InvalidCastException, MissingMethodException a dalším chybám. Popisuje následující doporučení:

První doporučení, pochopení výhod a nevýhod kontextů načítání, poskytuje základní informace pro ostatní doporučení, protože všechny závisí na znalosti kontextů načítání.

V rámci domény aplikace mohou být sestavení načítána do jednoho ze tří kontextů, nebo mohou být načteny bez kontextu:

  • Výchozí kontext obsahuje sestavení nalezené prozkoumáním globální mezipaměti sestavení (GAC), úložiště sestavení hostitele, pokud je module runtime hostován (například na serveru SQL Server), a prozkoumáním vlastností ApplicationBase a PrivateBinPath domény aplikace. Většina přetížení metody Load načítá sestavení do tohoto kontextu.

  • Kontext load-from obsahuje sestavení, která jsou načtena z míst, jenž nejsou prohledávána zavaděčem. Doplňky mohou být například nainstalovány v adresáři, který se nenachází v cestě aplikace. Assembly.LoadFrom , AppDomain.CreateInstanceFrom, a AppDomain.ExecuteAssembly jsou příklady metod, které načítají podle cesty.

  • Kontext reflection-only obsahuje sestavení, načítaná metodami ReflectionOnlyLoad a ReflectionOnlyLoadFrom. Kód v tomto kontextu nelze provést, proto zde nebude probírán. Další informace naleznete v tématu Postupy: Načtení sestavení do kontextu pouze pro reflexi.

  • Pokud je dočasné dynamické sestavení vygenerováno pomocí reflekce, sestavení není v žádném kontextu. Kromě toho většina sestavení, jenž jsou načteny pomocí metody LoadFile, je načtena bez kontextu, a sestavení, která jsou načtena z pole bajtů jsou načtena bez kontextu, pokud jejich identita (po aplikování zásad) stanoví, že jsou umístěny v globální mezipaměti sestavení (GAC).

Kontexty provádění mají výhody a nevýhody, popsané v následujících částech.

Dd153782.collapse_all(cs-cz,VS.110).gifVýchozí kontext načítání

Když jsou sestavení načtena do výchozího kontextu načítání, jejich závislosti jsou načteny automaticky. Závislosti, které jsou načteny do výchozího kontextu načítání, jsou nalezeny automaticky pro sestavení ve výchozím kontextu načítání nebo v kontextu load-from. Načtení podle identity sestavení zvyšuje stabilitu aplikací tím, že nejsou používány neznámé verze sestavení (viz sekce Vyhýbání se vazbám s částečnými názvy sestavení).

Použití výchozího kontextu načítání má následující nevýhody:

  • Závislosti, které jsou načteny v jiných kontextech, nejsou dostupné.

  • Ve výchozím kontextu načítání nelze načíst sestavení z míst mimo cestu zjišťování.

Dd153782.collapse_all(cs-cz,VS.110).gifKontext load-from

Kontext load-from umožňuje načíst sestavení z cesty, která se nenachází v cestě aplikace a proto není součástí zjišťování. To umožňuje nalezení závislostí a jejich načtení z dané cesty, protože je informace o cestě udržována kontextem. Sestavení v tomto kontextu navíc mohou použít závislosti, které jsou načteny do výchozího kontextu načítání.

Načítání sestavení pomocí metody Assembly.LoadFrom, nebo pomocí jedné z metod, které načítají pomocí cesty, má následující nevýhody:

  • Pokud je již načteno sestavení se stejnou identitou, metoda LoadFrom vrátí načtené sestavení, i když bylo zadáno s jinou cestu.

  • Pokud je sestavení načteno pomocí metody LoadFrom, a pokud se pokusí sestavení ve výchozím kontextu načítání načíst stejné sestavení pomocí zobrazovaného názvu, pokus o načtení selže. Tato situace může nastat, když je zrušena serializace sestavení.

  • Pokud je sestavení načteno pomocí metody LoadFrom, a cesta zjišťování zahrnuje sestavení se stejnou identitou ale v jiném umístění, může dojít k výjimkám InvalidCastException, MissingMethodException, nebo k jinému neočekávanému chování.

  • Metoda LoadFrom požaduje na určené cestě oprávnění FileIOPermissionAccess.Read a FileIOPermissionAccess.PathDiscovery, nebo WebPermission.

  • Pokud existuje nativní obraz sestavení, není použit.

  • Sestavení nelze načíst jako doménově neutrální.

  • V rozhraní .NET Framework verze 1.0 a 1.1 není zásada použita.

Dd153782.collapse_all(cs-cz,VS.110).gifŽádný kontext

Načítání bez kontextu je jedinou možností pro přechodná sestavení, která jsou generována pomocí reflekce. Načítání bez kontextu je jediným způsobem, jak načíst více sestavení do domény aplikace, které mají stejné identity. Nákladům na zjišťování se lze vyhnout.

Sestavení, která jsou načtena z bajtových polí, jsou načtena bez kontextu, pokud ale identita sestavení, která je vytvořena při použití zásad, neodpovídá identitě sestavení v globální mezipaměti sestavení (GAC). V takovém případě je sestavení načteno z globální mezipaměti sestavení (GAC).

Načítání sestavení bez kontextu má následující nevýhody:

  • Ostatní sestavení nelze svázat se sestaveními, která jsou načtena bez kontextu, pokud nezpracovávají událost AppDomain.AssemblyResolve.

  • Závislosti nejsou načteny automaticky. Lze je přednačíst bez kontextu, přednačíst je do výchozího kontextu, nebo je načíst zpracováním události AppDomain.AssemblyResolve.

  • Načtení více sestavení se stejnou identitou bez kontextu může způsobit problémy identity typu, podobné těm, způsobeným načítáním sestavení se stejnou identitou do více kontextů. Viz Zabránění načtení sestavení do více kontextů.

  • Pokud existuje nativní obraz sestavení, není použit.

  • Sestavení nelze načíst jako doménově neutrální.

  • V rozhraní .NET Framework verze 1.0 a 1.1 není zásada použita.

K vazbě sestavení s částečným názvem dochází, pokud je při načítání sestavení zadána pouze část názvu sestavení (FullName). Může být například zavolána metoda Assembly.Load s pouze jednoduchým názvem sestavení s vynecháním verze, kultury a tokenu veřejného klíče. Nebo může být zavolána metoda Assembly.LoadWithPartialName, která nejprve zavolá metodu Assembly.Load a pokud ta selže při vyhledání sestavení, prohledá globální mezipaměť sestavení (GAC) a načte nejnovější verzi sestavení, která je k dispozici.

Vázání pomocí částečného názvu může způsobit mnoho problémů, včetně následujících:

  • Metoda Assembly.LoadWithPartialName může načíst jiné sestavení se stejným jednoduchým názvem. Dvě aplikace mohou například nainstalovat do globální mezipaměti sestavení (GAC) dva zcela odlišná sestavení, která mají jednoduchý název GraphicsLibrary.

  • Sestavení, které je aktuálně načteno nemusí být zpětně kompatibilní. Například nezadání verze může způsobit načtení mnohem novější verze, než té, pro kterou byl program původně napsán. Změny v novější verzi mohou způsobit chyby v aplikaci.

  • Sestavení, které je aktuálně načteno, nemusí být dopředně kompatibilní. Například může být aplikace vytvořena a otestována s nejnovější verzí sestavení, kde ale může vázání pomocí částečného názvu načíst mnohem starší verzi, která nemá funkce, které aplikace používá.

  • Instalace nových aplikací můžete poškodit existující aplikace. Aplikace, která používá metodu LoadWithPartialName může být poškozena instalací novější, nekompatibilní verzí sdíleného sestavení.

  • Může dojít k načítání neočekávaných závislostí. Pokud jsou načtena dvě sestavení, která sdílejí závislost, jejich načtení s vázáním pomocí částečného názvu může vyústit v jedno sestavení používající komponentu, pro kterou nebylo sestaveno či testováno.

Kvůli potížím, které může způsobit, byla metoda LoadWithPartialName označena jako zastaralá. Je doporučeno místo ní použít metodu Assembly.Load a zadat celé zobrazované názvy sestavení. Viz Pochopení výhod a nevýhod kontextů načítání a Zvážení přepínání do výchozího kontextu.

Chcete-li použít metodu LoadWithPartialName, protože umožňuje snadné načítání sestavení, je třeba vzít v potaz, že selhání aplikace s chybovou zprávou, označující chybějící sestavení, může poskytnout uživateli lepší uživatelský zážitek, než automatické použití neznámé verze sestavení, které může způsobit nepředvídatelné chování a díry v zabezpečení.

Načtení sestavení do více kontextů může způsobit problémy s identitou typů. Pokud je stejný typ ze stejného sestavení načten do dvou různých kontextů, je to jako načtení dvou různých typů se stejným názvem. Při pokusu převést jeden typ na druhý je vyvolána výjimka InvalidCastException s nejasnou zprávou, že nelze typ MyType přetypovat na typ MyType.

Předpokládejme například, že je rozhraní ICommunicate deklarováno v sestavení s názvem Utility, na které program odkazuje a je na něj také odkazováno v jiných sestaveních, která tento program načítá. Tato ostatní sestavení obsahují typy, které implementují rozhraní ICommunicate a které může program použít.

Nyní zvažte, co se stane při spuštění programu. Sestavení, na která program odkazuje, jsou načtena do výchozího kontextu načítání. Při načítání cílového sestavení podle jeho identity pomocí metody Load dojde k jeho načtení do výchozího kontextu načítání a stejně tak i jeho závislostí. Program a cílové sestavení bude používat stejné sestavení Utility.

Předpokládejme však, že je cílové sestavení načteno pomocí cesty souboru pomocí metody LoadFile. Sestavení je načteno bez jakékoliv souvislosti, takže nejsou jeho závislosti automaticky načteny. Je možné mít pro poskytnutí závislosti obslužnou rutinu události AppDomain.AssemblyResolve, která může načítat sestavení Utility bez kontextu pomocí metody LoadFile. Nyní při vytváření instance typu, který je obsažen v cílovém sestavení, je při pokusu přiřadit jej do proměnné typu ICommunicate vyvolána výjimka InvalidCastException, protože se modul runtime domnívá, že jsou obě rozhraní ICommunicate, umístěné ve dvou kopiích sestavení Utility, různými typy.

Existuje mnoho dalších scénářů, v nichž může být sestavení načteno do více kontextů. Nejlepším řešením je předcházení konfliktů přemístěním cílového sestavení do cesty aplikace a použitím metody Load s plným zobrazovaným názvem. Sestavení je poté načteno do výchozího kontextu, a obě sestavení tak používají stejné sestavení Utility.

Pokud musí cílové sestavení zůstat mimo cestu k aplikaci, lze pro načtení do kontextu load-from použít metodu LoadFrom. Pokud bylo cílové sestavení zkompilováno s odkazem na sestavení Utility aplikace, dojde k použití sestavení Utility, které aplikace načetla do výchozího kontextu načítání. Všimněte si, že mohou nastat potíže, pokud existuje závislost mezi cílovým sestavením a kopií sestavení Utility, umístěného mimo cestu k aplikaci. Pokud je sestavení načteno do kontextu load-from předtím, než aplikace načte sestavení Utility, načtení aplikace se nezdaří.

Část Zvážení přepínání výchozího kontextu načítání se zabývá alternativami k použití načítání podle cesty souboru, například metodami LoadFile a LoadFrom.

Načtení více verzí sestavení do jednoho kontextu načítání může způsobit problémy s identitou typů. Pokud je načten stejný typ ze dvou verzí stejného sestavení, je to jako kdyby byly načteny dva různé typy se stejným názvem. Při pokusu převést jeden typ na druhý je vyvolána výjimka InvalidCastException s nejasnou zprávou, že nelze typ MyType přetypovat na typ MyType.

Program může například načíst jednu verzi sestavení Utility přímo a později může načíst jiné sestavení, které načte jinou verzi sestavení Utility. Nebo může chyba kódu způsobit dvě rozdílné cesty kódu v aplikaci a načíst tak různé verze sestavení.

Ve výchozím kontextu načítání může tento problém nastat při použití metody Assembly.Load a zadáním úplných zobrazovaných názvů sestavení, které obsahují čísla různých verzí. U sestavení, které jsou načteny bez kontextu může být problém způsoben použitím metody Assembly.LoadFile pro načtení stejného sestavení z různých cest. Modul runtime považuje dva sestavení, které jsou načteny z různých cest za různá sestavení, i v případě že jsou jejich identity stejné.

Kromě problémů identity typu, může způsobit více verzí sestavení výjimku MissingMethodException pokud je typ, který je načten z jedné verze sestavení předán do kódu, který očekává typ z jiné verze. Kód může například očekávat metodu, která byla přidána v novější verzi.

Při změně chování typu mezi verzemi může dojít k mnoha nepatrným chybám. Metoda může například vyvolat neočekávanou výjimku či vrátit neočekávanou hodnotu.

Je třeba pečlivě zkontrolovat kód a zajistit, že je načítána pouze jedna verze sestavení. Pro určení sestavení, která jsou v daném okamžiku načtena, lze použít metodu AppDomain.GetAssemblies.

Zkontrolujte vzory načítání a nasazení sestavení aplikace. Lze vyloučit sestavení, která jsou načítána z bajtových polí? Lze přesunout sestavení do cesty zjišťování? Pokud jsou sestavení umístěna v globální mezipaměti sestavení (GAC) nebo v cestě zjišťování domény aplikace (to znamená vlastnosti ApplicationBase a PrivateBinPath), lze sestavení načíst podle identity.

Pokud není možno umístit všechna sestavení do cesty zjišťování, je třeba zvážit možnosti jako použití modelu doplňku rozhraní .NET Framework, vložení sestavení do globální mezipaměti sestavení (GAC), nebo vytvoření aplikačních domén.

Dd153782.collapse_all(cs-cz,VS.110).gifZvažte použití modelu doplňku rozhraní .NET Framework

Pokud je pro implementaci doplňků, které nejsou obvykle nainstalovány v základní cestě aplikace, používán kontext load-from, použijte model doplňku rozhraní .NET Framework. Tento model poskytuje izolaci na úrovni domény nebo procesu, bez nutnosti spravovat samotné aplikační domény. Informace týkající se modelu doplňku viz Doplňky a rozšíření.

Dd153782.collapse_all(cs-cz,VS.110).gifZvažte použití globální mezipaměti sestavení

Umístění sestavení do globální mezipaměti sestavení (GAC) umožňuje získat výhody cesty sdíleného sestavení, která je mimo základní cestu aplikace, bez ztráty výhod výchozího kontextu načítání nebo s nevýhodami jiných kontextů.

Dd153782.collapse_all(cs-cz,VS.110).gifZvažte použití aplikačních domén

Pokud zjistíte, že některá sestavení nelze nasadit v aplikační cestě zjišťování, zvažte pro tato sestavení vytvoření nové domény aplikace. Pro tvorbu domény aplikace použijte AppDomainSetup a pro zadání cesty, která obsahuje sestavení, která je třeba načíst, použijte vlastnost AppDomainSetup.ApplicationBase. Pokud existuje více adresářů, které je třeba prohledat, lze nastavit proměnnou ApplicationBase na kořenový adresář a použít vlastnost AppDomainSetup.PrivateBinPath pro určení podadresářů, které mají být prozkoumány. Alternativně lze vytvořit více domén aplikace a nastavit vlastnost ApplicationBase každé domény aplikace na odpovídající cestu potřebných sestavení.

Všimněte si, že lze pro načtení těchto sestavení použít metodu Assembly.LoadFrom. Protože jsou nyní umístěny v cestě zjišťování, budou načtena do výchozího kontextu načítání namísto do kontextu load-from. Pro zajištění, že budou vždy použity správné verze je ale doporučován přechod na metodu Assembly.Load a zadání úplných zobrazovaných názvů sestavení.

Obsah vytvořený komunitou

Přidat
Zobrazit:
© 2014 Microsoft