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


87

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

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

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

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

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

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


9
Но .NET Core 5 - это не .NET Framework. Это не будущая версия .NET CLR 4.6, это еще одна отдельная вещь, тогда не волнуйтесь, AppDomain здесь, чтобы остаться.
Адриано Репетти

2
Я это понимаю, но если Microsoft утверждает, что .NET Core 5 будет многоплатформенным (Windows / Linux / Unix), то мне любопытно, почему они хотят удалить такую ​​основную функцию, как AppDomain.
Адитья Пасумарти

3
Я предполагаю (но это только мое мнение), что их сложнее реализовать в многоплатформенной манере, они замедляют многие вещи и добавляют сложности. Не так много людей используют их (по крайней мере, большинство людей не делают этого напрямую). Если они вам не нужны, вы можете использовать .NET Core. Если они вам нужны ... не используйте его (подумайте, ReFS vs NTFS). Просто .NET Core - это не будущее .NET (пока), а отдельный проект. Может быть, верстак, но точно не путь миграции или альтернатива 1: 1 (по крайней мере, сейчас).
Адриано Репетти

@AdrianoRepetti: подумайте о добавлении этого в качестве ответа, поскольку я думаю, что это полезно как таковое.
Патрик Хофман,

@PatrickHofman, это всего лишь мое мнение (2-й комментарий), я мог бы ответить как вики сообщества, но я оставляю эту обязанность кому-то, кто более свободно владеет английским!
Адриано Репетти

Ответы:


50

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

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


12
IMHO это не имеет ничего общего с размером, но с тем фактом, что CoreCLR не имеет строгого именования и, следовательно, имеет новую систему слияния и новый способ взглянуть на то, что такое сборка, ее идентичность и куда она загружается, это означает, что домен приложения как контейнер больше бесполезен.
Frans Bouma

7
Хм, нет. Для сохранения размера загрузки 6,6 МБ, конечно, потребовалось удалить более одной функции.
Hans Passant

7
Домены приложений могут быть полезны в полной версии .NET, даже если вы не используете строгое именование. (Например, способность доменов приложений обеспечивать изоляцию сбоев не зависит от строгого именования.) Таким образом, удаление строгого именования само по себе не является причиной для удаления доменов приложений.
Ян Гриффитс,

5
Я в замешательстве. Какая связь между .Net Core и Silverlight?
svick 02

10
Программисты склонны считать .NETCore новым. Microsoft очень мало делает, чтобы развеять это представление, ни в коей мере не меняя номер версии 5.0 на 1.0. CoreCLR существует очень давно, он начал свою жизнь как среда выполнения для .NET Compact. Silverlight и среда выполнения WinRT / UWP широко использовались для этого до того, как они открыли исходный код. Лучшая версия среды выполнения для выбора, которая ранее уже была перенесена на OSX и различные мобильные процессоры WinCE.
Ханс

46

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

В .NET Standard 2 AppDomainкласс находится там. Однако многие части этого API будут вызывать PlatformNotSupportedException.NET Core.

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

В FAQ по .NET Standard есть следующее объяснение :

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

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

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

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


20

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

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

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

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


Один вопрос, что вы имеете в виду For code isolation, we recommend processes and/or containers... Есть ли API-интерфейс контейнера в ядре .net?
Ivandro Jao

@IvandroIsmael, они означают «разделить ваше отдельное приложение / модуль на отдельные взаимодействующие приложения / модули / процессы / контейнеры» (скорее всего - на микросервисы), т.е. провести рефакторинг вашего приложения, чтобы не использовать AppDomains для изоляции кода
Burst

10

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


5

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


5

Вам больше не нужны 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()
     {}
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.