Czy istnieje ważny powód, dla którego firma Microsoft zdecydowała się nie obsługiwać AppDomains w .NET Core?
AppDomains są szczególnie przydatne podczas tworzenia długo działających aplikacji serwerowych, w których możemy chcieć zaktualizować zestawy ładowane przez serwer w sposób łagodny, bez wyłączania serwera.
Bez AppDomains, jak zamierzamy zastąpić nasze zestawy w długotrwałym procesie serwera?
AppDomains zapewniają nam również sposób na izolowanie różnych części kodu serwera. Tak jak niestandardowy serwer WebSocket może mieć kod gniazda w podstawowej domenie aplikacji, podczas gdy nasze usługi działają w dodatkowej domenie aplikacji.
Bez AppDomains powyższy scenariusz nie jest możliwy.
Widzę argument, który może mówić o używaniu koncepcji maszyn wirtualnych w chmurze do obsługi zmian w montażu i bez konieczności ponoszenia narzutu AppDomains. Ale czy tak myśli lub mówi Microsoft? czy mają konkretny powód i alternatywy dla powyższych scenariuszy?
Odpowiedzi:
Celem podzbioru .NETCore było utrzymanie małej instalacji .NET . I łatwe do przenoszenia. Dlatego możesz, powiedzmy, uruchomić aplikację Silverlight zarówno w systemie Windows, jak i OSX i nie czekać zbyt długo, kiedy odwiedzasz stronę internetową. Pobranie i zainstalowanie pełnego środowiska uruchomieniowego i frameworka zajmuje kilka sekund.
Utrzymanie jej małego rozmiaru nieuchronnie wymaga wycięcia cech. Zdalny dostęp był bardzo wysoko na tej liście, jest dość drogi. W przeciwnym razie dobrze ukryty, ale można na przykład zobaczyć, że delegaci nie mają już funkcjonalnej metody BeginInvoke (). Dzięki temu AppDomain również znalazł się na liście elementów ciętych, nie możesz uruchamiać kodu w domenie aplikacji bez obsługi zdalnej. Jest to więc całkowicie zgodne z projektem.
źródło
Aktualizacja dla .NET Standard 2 i .NET Core 2
W .NET Standard 2
AppDomain
klasa jest tam. Jednak wiele części tego interfejsu API spowoduje zgłoszeniePlatformNotSupportedException
dla platformy .NET Core.Głównym powodem, dla którego wciąż tam jest, są podstawowe rzeczy, takie jak rejestracja nieobsługiwanego programu obsługi wyjątków, który będzie działał.
NET Standard FAQ zawiera następujące wyjaśnienie :
Poza tym górna odpowiedź i inne odpowiedzi również ładnie wyjaśniają, dlaczego większość AppDomain była nadal ograniczona (np. Zgłasza nieobsługiwany wyjątek).
źródło
Domeny aplikacji
Dlaczego zostało przerwane? AppDomains wymagają obsługi w czasie wykonywania i generalnie są dość drogie. Chociaż nadal jest implementowany przez CoreCLR, nie jest dostępny w .NET Native i nie planujemy dodawania tam tej funkcji.
Czego powinienem użyć zamiast tego? AppDomains były używane do różnych celów. Do izolacji kodu zalecamy procesy i / lub kontenery. W przypadku dynamicznego ładowania zestawów zalecamy nową klasę AssemblyLoadContext.
Źródło z blogu MSDN
źródło
For code isolation, we recommend processes and/or containers
... Czy w .net core jest dostępny interfejs API kontenera?W pewnym momencie usłyszałem, że rozładowywanie zestawów byłoby możliwe bez korzystania z domen. Wydaje mi się, że
System.Runtime.Loader.AssemblyLoadContext
typ w System.Runtime.Loader.dll jest związany z tą pracą, ale nie widzę tam jeszcze niczego, co umożliwiałoby wyładowanie.źródło
Nie potrzebujesz już AppDomains, masz teraz LoadContexts:
public class CollectibleAssemblyLoadContext : AssemblyLoadContext { public CollectibleAssemblyLoadContext() : base(isCollectible: true) { } protected override Assembly Load(AssemblyName assemblyName) { return null; } } byte[] result = null; // Assembly Emit-result from roslyn System.Runtime.Loader.AssemblyLoadContext context = new CollectibleAssemblyLoadContext(); System.IO.Stream ms = new System.IO.MemoryStream(result); System.Reflection.Assembly assembly = context.LoadFromStream(ms); System.Type programType = assembly.GetType("RsEval"); MyAbstractClass eval = (MyAbstractClass )System.Activator.CreateInstance(programType); eval.LoadContext = context; eval.Stream = ms; // do something here with the dynamically created class "eval"
a potem możesz powiedzieć
eval.LoadContext.Unload(); eval.Stream.Dispose();
Bonus, jeśli umieścisz to w interfejsie IDisposable klasy abstrakcyjnej, możesz po prostu użyć using, jeśli chcesz.
Uwaga:
Zakłada to stałą klasę abstrakcyjną we wspólnym zestawie
public abstract class MyAbstractClass { public virtual void foo() {} }
oraz klasę generowaną dynamicznie (przy użyciu Roslyn), odwołującą się do klasy abstrakcyjnej we wspólnym zestawie, która implementuje np .:
public class RsEval: MyAbstractClass { public override void foo() {} }
źródło
Słyszałem w opinii społeczności lub rozmowach o firmie Microsoft, że funkcja izolacji AppDomains jest lepiej obsługiwana przez procesy (a właściwie wspólny wzorzec na innych platformach), a wyładowanie jest rzeczywiście planowane jako normalna funkcja niezwiązana z AppDomains.
źródło