ali*_*hoo 12 c# appdomain dynamic-loading .net-assembly appdomainsetup
我编写了一小段关于动态加载程序集和从这些程序集创建类实例的代码,包括可执行文件,要动态加载的测试库和用于将动态程序集加载到新程序集的加载程序库Appdomain.Loader库由可执行文件和动态库引用.
//executable
[System.STAThreadAttribute()]
[System.LoaderOptimization(LoaderOptimization.MultiDomain)]
static void Main(string[] args)
{
AppDomainSetup domainSetup = new AppDomainSetup()
{
ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,
ApplicationName = AppDomain.CurrentDomain.SetupInformation.ApplicationName,
LoaderOptimization = LoaderOptimization.MultiDomain
};
AppDomain childDomain = AppDomain.CreateDomain("MyDomain", null, domainSetup);
Console.WriteLine(AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString());
Console.WriteLine(childDomain.SetupInformation.LoaderOptimization.ToString());
byte[] assembly = null;
string assemblyName = "CSTestLib";
using (FileStream fs = new FileStream(assemblyName+".dll",FileMode.Open))
{
byte[] byt = new byte[fs.Length];
fs.Read(byt,0,(int)fs.Length);
assembly = byt;
}
object[] pararmeters = {assemblyName,assembly};
string LoaderAssemblyName = typeof(AssemblyLoader).Assembly.FullName;
string LoaderClassName = typeof(AssemblyLoader).FullName;
AssemblyLoader assloader = (AssemblyLoader)childDomain.CreateInstanceAndUnwrap(LoaderAssemblyName,LoaderClassName , true, BindingFlags.CreateInstance, null, parameters, null, null);
object obj = assloader.Load("CSTestLib.Class1");
object obj2 = assloader.Load("CSTestLib.Class2");
AppDomain.Unload(childDomain);
Console.ReadKey();
}
//Dynamic Lib
using System;
namespace CSTestLib
{
public class Class1 :MarshalByRefObject
{
public Class1() { }
}
public class Class2 : MarshalByRefObject
{
public Class2() { }
}
}
//Loader Library
using System;
namespace LoaderLibrary
{
public class AssemblyLoader : MarshalByRefObject
{
string assemblyName;
public AssemblyLoader(string assName, byte[] ass)
{
assemblyName = assName;
AppDomain.CurrentDomain.Load(ass);
Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + " " + AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString());
}
public object Load(string className)
{
object ret = null;
try
{
ret = AppDomain.CurrentDomain.CreateInstanceAndUnwrap(assemblyName, className);
}
catch (System.Exception ex)
{
Console.WriteLine(ex.Message);
}
return ret;
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这里我设置LoaderOptimizationAttribute的main()方法,但AppDomain.CurrentDomain.SetupInformation.LoaderOptimization.ToString();说这是NotSpecified为什么呢?
之间的差异MultiDomain和MultiDomainHost不那么清晰.是MultiDomainHost只GAC组件?对于我的情况哪个更合适?
根据这个
无法使用Assembly类的LoadFrom方法为加载到load-from上下文中的程序集共享JIT编译的代码,也不能使用指定字节数组的Load方法的重载从映像加载JIT编译的代码.
那么如何检测程序集是否加载域中性?怎么能保证我加载域中立?
Alo*_*aus 13
如果使用NGen预编译程序集以加速应用程序的热启动,则此属性仅起作用.指定MultiDomain或MultiDomainHost启用预编译(ngenned)程序集的用法时.您可以使用Process Explorer对其进行验证,您可以在其中查看已加载模块的列表.
如果您的应用程序包含多个共享程序集的可执行实例,那么这是最大的启动时间节省之一.这使.NET能够在进程之间共享代码页,从而节省实际内存(一个程序集只在物理内存中存在一次,但在一个或多个进程之间共享),并防止在每个进程中反复JITing相同的代码这需要花费时间,生成的代码效率稍低,因为它可以使用常规JIT进行编译,JIT可以使用更多动态数据来生成最有效的代码.
在您的示例中,您将程序集加载到位于托管堆中的字节数组中,并增加您的专用字节数.这使得无法在进程之间共享数据.只有在硬盘上具有对应物的只读页面才能在进程之间共享.这就是属性无效的原因.如果您在热启动性能的2倍之后,这就是您要寻找的属性.对于其他任何事情都不相关.
现在回到你原来的问题:
MultiDomain忽略此属性.当您在调试器之外启动它时,您将获得预期的结果.MultiDomainHost的确AppDomain仅为已签名的程序集启用中性,而不共享所有其他程序集.