问题描述
我有程序,它创建 AppDomain
,在其中加载程序集 prelude
,然后卸载 AppDomain
。最后,程序列出了来自默认 appdomain 的程序集。它是程序的简化版本。在下一个版本中,prelude.dll
将在运行时更改并通过 appdomain 持续执行/卸载。
namespace appdomaintest
{
class Program
{
static void log_assemblies(AppDomain domain)
{
foreach (var item in domain.GetAssemblies())
{
Console.WriteLine($"{domain.FriendlyName} : {item.FullName}");
}
}
static void Main(string[] args)
{
{
var prelude_domain = AppDomain.CreateDomain("PreludeDomain#1",null,null);
var asm = prelude_domain.Load(new System.Reflection.AssemblyName("prelude"));
var myint = prelude_domain.CreateInstanceAndUnwrap("prelude","prelude.MyInt");
myint.GetType().getmethod("show").Invoke(myint,new object[0]);
AppDomain.Unload(prelude_domain);
Console.WriteLine("AppDomain was unloaded");
}
log_assemblies(AppDomain.CurrentDomain);
}
}
}
这是prelude.dll
的内容
public class MyInt : MarshalByRefObject
{
public MyInt()
{
Console.WriteLine($"MyInt was constructed in {AppDomain.CurrentDomain.FriendlyName}");
}
public void show()
{
Console.WriteLine($"show in {AppDomain.CurrentDomain.FriendlyName}");
}
}
这是程序的输出:
MyInt was constructed in PreludeDomain#1
show in PreludeDomain#1
AppDomain was unloaded
appdomaintest.exe : mscorlib,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089
appdomaintest.exe : appdomaintest,Version=1.0.0.0,PublicKeyToken=null
appdomaintest.exe : prelude,PublicKeyToken=null
不幸的是,我发现我的默认应用程序域包含 prelude.dll
程序集。据我了解,它会一直持续到我的程序执行结束。有什么方法可以防止将其加载到默认应用程序域?在未来的版本中,prelude.dll
将被重复加载/卸载(它的元数据也将被修改)。这就是为什么这种行为不适合我的目的。
在我看来,创建代理对象可能会导致将元数据加载到默认域。但是我怎样才能卸载它们呢?
解决方法
它会保留,是的。没有办法解决它,因为微软在此处声明这是不可能的:https://docs.microsoft.com/en-us/dotnet/framework/app-domains/how-to-unload-an-application-domain。
使用与另一个进程的进程间通信。您可以启动进程并在其中加载任何内容,直到它变得臃肿,然后您只需杀死它并重新开始。
您从中获得的一个好处 - 没有人会导致您的应用程序因意外调用此库中不安全的内容而崩溃。