Есть ли веская причина, по которой Microsoft решила не поддерживать домены приложений в .NET Core?
Домены приложений особенно полезны при создании длительно работающих серверных приложений, где мы можем захотеть обновить сборки, загруженные сервером, изящным образом, не выключая сервер.
Как мы собираемся заменить наши сборки в длительном серверном процессе без доменов приложений?
AppDomains также предоставляют нам способ изолировать различные части серверного кода. Например, пользовательский сервер websocket может иметь код сокета в основном домене приложения, а наши службы работают во вторичном домене приложения.
Без доменов приложений описанный выше сценарий невозможен.
Я вижу аргумент, который может говорить об использовании концепции виртуальных машин в облаке для обработки изменений сборки и отсутствия накладных расходов на домены приложений. Но так ли думает или говорит Microsoft? или у них есть конкретная причина и альтернативы для вышеперечисленных сценариев?
Ответы:
Задача подмножества .NETCore заключалась в том, чтобы установить .NET небольшого размера . И легко портировать. Вот почему вы можете, скажем, запустить приложение Silverlight как в Windows, так и в OS X и не ждать очень долго при посещении веб-страницы. Загрузка и установка полной среды выполнения и фреймворка занимает несколько секунд, плюс-минус.
Чтобы он оставался маленьким, неизбежно нужно вырезать элементы. Удаленное взаимодействие было очень высоко в этом списке, оно довольно дорогое. В противном случае это хорошо скрыто, но вы можете, например, увидеть, что делегаты больше не имеют функционального метода BeginInvoke (). Что также помещает AppDomain в список вырезок, вы не можете запускать код в домене приложения без поддержки удаленного взаимодействия. Так что это полностью задумано.
источник
Обновление для .NET Standard 2 и .NET Core 2
В .NET Standard 2
AppDomain
класс находится там. Однако многие части этого API будут вызыватьPlatformNotSupportedException
.NET Core.Основная причина, по которой он все еще существует, - это основные вещи, такие как регистрация обработчика необработанных исключений, который будет работать.
В FAQ по .NET Standard есть следующее объяснение :
Помимо этого, главный ответ и другие ответы также хорошо объясняют, почему большая часть AppDomain все еще была вырезана (например, генерирует неподдерживаемое исключение).
источник
Домены приложений
Почему его сняли с производства? Домены приложений требуют поддержки во время выполнения и обычно довольно дороги. Хотя он все еще реализован CoreCLR, он недоступен в .NET Native, и мы не планируем добавлять туда эту возможность.
Что мне использовать вместо этого? Домены приложений использовались для разных целей. Для изоляции кода мы рекомендуем процессы и / или контейнеры. Для динамической загрузки сборок мы рекомендуем новый класс AssemblyLoadContext.
Источник из блога MSDN
источник
For code isolation, we recommend processes and/or containers
... Есть ли API-интерфейс контейнера в ядре .net?В какой-то момент я услышал, что выгрузка сборок будет включена без использования доменов. Я думаю, что
System.Runtime.Loader.AssemblyLoadContext
тип в System.Runtime.Loader.dll имеет отношение к этой работе, но я пока не вижу там ничего, что разрешает выгрузку.источник
Я слышал в выступлении сообщества или в некоторых разговорах о Microsoft, что функция изоляции доменов приложений лучше обрабатывается процессами (и на самом деле является общим шаблоном на других платформах), и выгрузка действительно запланирована как обычная функция, не связанная с доменами приложений.
источник
Вам больше не нужны AppDomains, теперь у вас есть 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"
и тогда вы можете сказать
eval.LoadContext.Unload(); eval.Stream.Dispose();
Бонус, если вы поместите это в интерфейс IDisposable абстрактного класса, тогда вы можете просто использовать using, если хотите.
Примечание:
это предполагает фиксированный абстрактный класс в общей сборке.
public abstract class MyAbstractClass { public virtual void foo() {} }
и динамически генерируемый во время выполнения класс (с использованием Roslyn), ссылающийся на абстрактный класс в общей сборке, который, например, реализует:
public class RsEval: MyAbstractClass { public override void foo() {} }
источник