Нет доменов приложений в.NET Core! Зачем?

Есть ли веская причина, почему Microsoft решила не поддерживать домены приложений в.NET Core?

Домены приложений особенно полезны при создании долго работающих серверных приложений, где мы можем захотеть обновить сборки, загруженные сервером, изящно, без остановки сервера.

Без доменов приложений, как мы собираемся заменить наши сборки в длительном процессе сервера?

Домены приложений также предоставляют нам способ изолировать различные части серверного кода. Например, пользовательский сервер веб-сокетов может иметь код сокета в первичном домене приложений, в то время как наши службы работают во вторичном домене приложений.

Без доменов приложений описанный выше сценарий невозможен.

Я вижу аргумент, который может говорить об использовании концепции облачных виртуальных машин для обработки изменений в сборке и не требует дополнительных затрат на домены приложений. Но это то, что Microsoft думает или говорит? или у них есть конкретные причины и альтернативы для вышеуказанных сценариев?

5 ответов

Обновление для.NET Standard 2 и.NET Core 2

В.NET Standard 2 AppDomain класс там. Тем не менее, многие части этого API PlatformNotSupportedException для.NET Core.

Основная причина, по которой он все еще существует, заключается в базовых вещах, таких как регистрация необработанного обработчика исключений, который будет работать.

.NET Standard FAQ имеет такое объяснение:

Является ли AppDomain частью.NET Standard?

Тип AppDomain является частью.NET Standard. Не все платформы будут поддерживать создание новых доменов приложений, например, .NET Core не будет, поэтому метод AppDomain.CreateDomain, пока он доступен в.NET Standard, может вызвать исключение PlatformNotSupportedException.

Основная причина, по которой мы раскрываем этот тип в.NET Standard, заключается в том, что его использование довольно велико и обычно не связано с созданием новых доменов приложений, а связано с взаимодействием с текущим доменом приложений, например с регистрацией необработанного обработчика исключений или запросом базового каталога приложения.,

Кроме того, верхний ответ и другие ответы также хорошо объясняют, почему основная часть AppDomain все еще была сокращена (например, выбрасывает неподдерживаемое исключение).

Смысл подмножества.NETCore состоял в том, чтобы сохранить установку.NET небольшой. И легко портировать. Вот почему вы можете, скажем, запустить приложение Silverlight как на Windows, так и на OSX, и не очень долго ждать при посещении веб-страницы. Загрузка и установка полной среды выполнения и фреймворка занимает несколько секунд.

Сохранение его небольшим неизбежно требует сокращения функций. Remoting была очень высоко в этом списке, это довольно дорого. В противном случае он хорошо спрятан, но вы можете, например, увидеть, что у делегатов больше нет функционального метода BeginInvoke(). Кроме того, в список вырезов добавлен AppDomain, вы не можете запускать код в домене приложений без поддержки удаленного взаимодействия. Так что это полностью задумано.

Домены приложений

Почему это было прекращено? Домены приложений требуют поддержки во время выполнения и, как правило, довольно дороги. Хотя он по-прежнему реализован в CoreCLR, он не доступен в.NET Native, и мы не планируем добавлять эту возможность там.

Что я должен использовать вместо этого? Домены приложений использовались для разных целей. Для изоляции кода мы рекомендуем процессы и / или контейнеры. Для динамической загрузки сборок мы рекомендуем новый класс AssemblyLoadContext.

Источник из блога MSDN

Вам больше не нужны 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, если хотите.

В какой-то момент я услышал, что выгрузка сборок будет включена без использования доменов. Я думаю, что System.Runtime.Loader.AssemblyLoadContext тип System.Runtime.Loader.dll связан с этой работой, но я пока не вижу там ничего, что бы разрешало выгрузку.

Я слышал в отчете сообщества или в разговоре о Microsoft, что функция изоляции доменов приложений лучше обрабатывается процессами (и фактически общей схемой на других платформах), и выгрузка действительно запланирована как обычная функция, не связанная с доменами приложений.

Другие вопросы по тегам