如何使用CodeDOM在AppDomain中创建和加载程序集? [英] How can I use CodeDOM to create and load an assembly in an AppDomain?
问题描述
我正在一个项目中,该项目将使用CodeDOM创建一个评估用户定义的表达式的类,为该类创建一个程序集并加载该程序集.由于可以有很多用户定义的表达式,因此我想首先创建一个AppDomain,执行该AppDomain中的程序集的CodeDOM创建/加载和执行,然后卸载该AppDomain.
I am working on a project that will use CodeDOM to create a class that evaluates a user-defined expression, creates an assembly for the class, and loads the assembly. Since there can be a fair number of user-defined expressions, I would like to first create an AppDomain, execute the CodeDOM creation/loading and executing for the assembly within that AppDomain, and then unload the AppDomain.
我已经搜索了很多,并找到了许多有关如何将现有程序集加载到AppDomain中的示例,但是似乎找不到一个可以向我展示如何从内部创建程序集的示例 AppDomain.
I've searched quite a bit, and found many examples of how to load an existing assembly into an AppDomain, but I can't seem to find one that shows me how to create the assembly from within the AppDomain.
此示例( DynamicCode )使用CodeDOM创建了一个程序集,并且然后将其加载到AppDomain中,但是,作者正在将程序集生成到磁盘.我希望在内存中生成程序集,这样就不必管理所生成程序集的清理. (即使这确实会在临时文件夹中创建一个.dll).
This example (DynamicCode) creates an assembly using CodeDOM, and then loads it into an AppDomain, however, the author is generating the assembly to disk. I would prefer to generate the assembly in memory, so that I do not have to manage the cleanup of the generated assemblies. (even though this does create a .dll in a temp folder).
任何人都可以给我指出一个如何执行此操作的示例吗?
Can anyone point me to an example of how to do this?
任何帮助将不胜感激.
我已经从代码中摘录了一些摘录,以便您都可以体会到到目前为止的情况:
I've included some excerpts from my code so you can all get a feel for what I have so far:
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中.
I believe these code snippets show the basic functionality of my project. Now all I need to do is wrap it in its own AppDomain.
推荐答案
I found the answer that I was looking for at http://www.softwareinteractions.com/blog/2010/2/7/loading-and-unloading-net-assemblies.html. He has a nice article detailing the creation of an AppDomain and loading an assembly as a plugin. I followed his example and was able to create an AppDomain, create a proxy for my ExpressionEvaluator class factory and successfully call it and receive results.
这篇关于如何使用CodeDOM在AppDomain中创建和加载程序集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!