2016-11-16 77 views
0

我正在尝试检查程序集的某些元数据而不将其永久加载到我的应用程序中。为此,我创建一个临时的​​AppDomain,将程序集加载到它中,然后卸载整个​​。根据this question的答案,这是“正确”的方式来做到这一点。AppDomain.Unload不会卸载程序集

但卸载程序集后,它仍然保留在当前AppDomain中。为什么?

this question的回答表明程序集可以被“放入”当前域,但我不明白我的例子中这怎么可能。应用程序的其余部分根本不使用程序集,甚至没有被引用。即使在装配后立即卸载sandobx,观察到的行为仍然存在。

This article表示域中立程序集不能以这种方式卸载。这是原因吗?如果是的话,我可以以某种方式阻止大会被视为领域中立?

private void Check() 
{ 
    string assemblyName = "SomeUnrelatedAssembly"; 
    var sandbox = AppDomain.CreateDomain("sandbox"); //create a discardable AppDomain 
    //load the assembly to the sandbox 
    byte[] arr; 
    using (var memoryStream = new MemoryStream()) 
    { 
     using (var fileStream = new FileStream($"{assemblyName}.dll", FileMode.Open)) 
      fileStream.CopyTo(memoryStream); 
     arr = memoryStream.ToArray(); 
    } 

    Console.WriteLine(IsAssemblyLoaded(assemblyName)); //prints false 
    sandbox.Load(arr); 

    //and unload it  
    AppDomain.Unload(sandbox);  
    Console.WriteLine(IsAssemblyLoaded(assemblyName)); //prints true! 
} 

private static bool IsAssemblyLoaded(string assemblyName) 
{ 
    return AppDomain.CurrentDomain.GetAssemblies().Any(a => a.FullName.Contains(assemblyName)); 
} 

EDIT:我已经检查与处理资源管理器(如this)加载过程。加载的程序集不是域中立的。

+0

你可以告诉我们什么'//检查索姆e元数据代码看起来像?尽管在沙盒域中加载程序集,但可能会通过当前域中的元数据。 –

+0

即使'sanbox.Load'和'AppDomain.Unload'指令之间没有任何内容,行为也是一样的。 – tearvisus

回答

0

你是对的。你的程序集被认为是域中立的,并跨应用程序域共享。

使用AppDomain.CreateDomain重载允许您提供设置信息:

信息:

AppDomainSetup info = new AppDomainSetup(); 
info.ApplicationBase = domainDir; 
info.ApplicationName = executableNameNoExe; 
info.LoaderOptimization = LoaderOptimization.SingleDomain; 

变化:

AppDomain.CreateDomain("sandbox"); 

要:

AppDomain.CreateDomain("sandbox",null, info); 
+0

不幸的是,它不起作用。第二个检查仍然打印真实。 – tearvisus

+0

如果在“Check”调用之前调用'IsAssemblyLoaded()'会怎么样?可能是它早些时候被加载? –

+0

通过'第二次检查'我的意思是第二次'IsAssemblyLoaded'调用。这个例子中的Check方法只被调用一次。 – tearvisus