[英]How to Load an Assembly to AppDomain with all references recursively?
[英]How can I use CodeDOM to create and load an assembly in an AppDomain?
我正在开发一个项目,该项目将使用 CodeDOM 创建一个评估用户定义表达式的类,为该类创建一个程序集,并加载该程序集。 由于可以有相当数量的用户定义表达式,我想首先创建一个 AppDomain,为该 AppDomain 中的程序集执行 CodeDOM 创建/加载和执行,然后卸载 AppDomain。
我搜索了不少,并且发现了如何加载现有装配成一个AppDomain的例子很多,但我似乎无法找到一个节目我如何从内部的AppDomain创建装配。
此示例 ( DynamicCode ) 使用 CodeDOM 创建一个程序集,然后将其加载到 AppDomain 中,但是,作者将程序集生成到磁盘。 我更愿意在内存中生成程序集,这样我就不必管理生成的程序集的清理工作。 (即使这确实在临时文件夹中创建了一个 .dll)。
谁能指出我如何做到这一点的例子?
任何帮助将不胜感激。
我已经从我的代码中摘录了一些摘录,这样你们都可以了解我到目前为止的内容:
private string CreateSource()
{
CodeCompileUnit codeUnit = new CodeCompileUnit();
CodeNamespace codeNamespace = new CodeNamespace(Namespace);
CodeTypeDeclaration codeClass = new CodeTypeDeclaration
{
Name = "ExpressionEvaluator",
IsClass = true,
TypeAttributes = TypeAttributes.Public | TypeAttributes.Sealed
};
codeNamespace.Types.Add(codeClass);
codeUnit.Namespaces.Add(codeNamespace);
AddMethods(codeClass);
string result = GenerateSourceCode(codeUnit);
return result.ToString();
}
private CompilerResults CompileSource(string source)
{
using (CodeDomProvider provider = new CSharpCodeProvider())
{
CompilerParameters parameters = CreateCompilerParameters();
CompilerResults result = CompileCode(provider, parameters, source);
return result;
}
}
private static CompilerParameters CreateCompilerParameters()
{
CompilerParameters result = new CompilerParameters
{
CompilerOptions = "/target:library",
GenerateExecutable = false,
GenerateInMemory = true
};
result.ReferencedAssemblies.Add("System.dll");
return result;
}
private object RunEvaluator(CompilerResults compilerResults)
{
object result = null;
Assembly assembly = compilerResults.CompiledAssembly;
if (assembly != null)
{
string className = "ExpressionEvaluator";
object instance = assembly.CreateInstance("Lab.ExpressionEvaluator");
Module[] modules = assembly.GetModules(false);
Type type = (from t in modules[0].GetTypes()
where t.Name == className
select t).FirstOrDefault();
MethodInfo method = (from m in type.GetMethods()
where m.Name == "Evaluate"
select m).FirstOrDefault();
result = method.Invoke(instance, null);
}
else
{
throw new Exception("Unable to load Evaluator assembly");
}
return result;
}
我相信这些代码片段显示了我项目的基本功能。 现在我需要做的就是将它包装在它自己的 AppDomain 中。
鸡和蛋的问题。 您需要一个小的引导程序程序集,您可以将其加载到新的 AppDomain 中。 使用一个众所周知的类加载 CodeDom 生成的程序集并使其运行。
使用 GenerateInMemory 执行此操作毫无意义,您必须将其序列化到新的 AppDomain 中。 这只是一堆开销,还不如从磁盘加载它,无论如何它都在那里。 而且它已经在内存中了。 文件系统缓存的内存。 加载它会非常快,因为它实际上不必从磁盘上读取。
我在http://www.softwareinteractions.com/blog/2010/2/7/loading-and-unloading-net-assemblies.html找到了我正在寻找的答案。 他有一篇很好的文章,详细介绍了 AppDomain 的创建和作为插件加载程序集。 我按照他的例子,能够创建一个 AppDomain,为我的 ExpressionEvaluator 类工厂创建一个代理,并成功调用它并接收结果。
定义动态程序集时只需使用AssemblyBuilderAccess.Run
http://msdn.microsoft.com/en-us/library/system.reflection.emit.assemblybuilderaccess.aspx
可以执行动态程序集,但不能保存。
CompilCode
方法从何而来? 这似乎是最重要的部分,而您决定将其排除在外?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.