Existe um forte motivo pelo qual a Microsoft optou por não oferecer suporte a AppDomains no .NET Core?
AppDomains são particularmente úteis ao construir aplicativos de servidor de longa execução, onde podemos querer atualizar os assemblies carregados pelo servidor de uma maneira elegante, sem desligar o servidor.
Sem AppDomains, como vamos substituir nossos assemblies em um processo de servidor de longa duração?
Os AppDomains também nos fornecem uma maneira de isolar diferentes partes do código do servidor. Por exemplo, um servidor websocket personalizado pode ter código de soquete no appdomain primário, enquanto nossos serviços são executados no appdomain secundário.
Sem AppDomains, o cenário acima não é possível.
Eu posso ver um argumento que pode falar sobre o uso do conceito de nuvem de VMs para lidar com alterações de montagem e não ter que incorrer na sobrecarga de AppDomains. Mas é isso que a Microsoft pensa ou diz? ou eles têm uma razão específica e alternativas para os cenários acima?
Respostas:
O objetivo do subconjunto .NETCore era manter uma pequena instalação do .NET . E fácil de transportar. É por isso que você pode, digamos, executar um aplicativo Silverlight no Windows e no OSX e não esperar muito tempo ao visitar a página da web. Baixar e instalar o tempo de execução e a estrutura completos leva alguns segundos, mais ou menos.
Mantê-lo pequeno inevitavelmente requer que recursos sejam cortados. Remoto estava no topo dessa lista, é muito caro. Caso contrário, bem escondido, mas você pode, por exemplo, ver que os delegados não têm mais um método BeginInvoke () funcional. O que também colocou AppDomain na lista de corte, você não pode executar o código em um domínio de aplicativo sem suporte remoto. Portanto, isso é inteiramente intencional.
fonte
Atualização para .NET Standard 2 e .NET Core 2
No .NET Standard 2, a
AppDomain
classe está lá. No entanto, muitas partes dessa API lançarão umPlatformNotSupportedException
para .NET Core.A principal razão ele ainda está lá é para coisas básicas como registrar um manipulador de exceção não tratada que vai trabalhar.
As perguntas frequentes do .NET Standard têm esta explicação :
Além disso, a resposta principal e outras respostas também explicam bem por que a maior parte do AppDomain ainda foi cortada (por exemplo, lança uma exceção não suportada).
fonte
Domínios do aplicativo
Por que foi descontinuado? AppDomains requerem suporte de tempo de execução e geralmente são bastante caros. Embora ainda implementado pelo CoreCLR, não está disponível no .NET Native e não planejamos adicionar esse recurso lá.
O que devo usar no lugar? AppDomains foram usados para diferentes fins. Para isolamento de código, recomendamos processos e / ou contêineres. Para carregamento dinâmico de assemblies, recomendamos a nova classe AssemblyLoadContext.
Fonte do MSDN Blog
fonte
For code isolation, we recommend processes and/or containers
... Existe uma API de contêiner disponível no núcleo .net?Em um ponto, ouvi que descarregar assemblies seria habilitado sem o uso de domínios. Acho que o
System.Runtime.Loader.AssemblyLoadContext
tipo em System.Runtime.Loader.dll está relacionado a este trabalho, mas não vejo nada lá que permita o descarregamento ainda.fonte
Eu ouvi em um stand da comunidade ou alguma conversa da Microsoft que o recurso de isolamento de AppDomains é melhor tratado por processos (e na verdade o padrão comum em outras plataformas) e o descarregamento é planejado como um recurso normal não relacionado a AppDomains.
fonte
Você não precisa mais de AppDomains, agora você tem 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"
e então você pode dizer
eval.LoadContext.Unload(); eval.Stream.Dispose();
Bônus se você colocar isso na interface IDisposable da classe abstrata, então você pode apenas usar using, se quiser.
Nota:
Isso pressupõe uma classe abstrata fixa em uma montagem comum
public abstract class MyAbstractClass { public virtual void foo() {} }
e uma classe gerada dinamicamente em tempo de execução (usando Roslyn), referenciando a classe abstrata no assembly comum, que implementa, por exemplo:
public class RsEval: MyAbstractClass { public override void foo() {} }
fonte