2010-08-18 111 views
4

我正在研究一个项目,该项目将使用CodeDOM创建一个评估用户定义表达式的类,为该类创建一个程序集并加载程序集。由于可以有相当数量的用户定义的表达式,我想先创建一个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中。

回答

3

鸡和鸡蛋的问题。您需要一个可以加载到新AppDomain中的小引导程序集。加载CodeDom生成的程序集并着手它的知名类。

用GenerateInMemory做这件事很没意义,你必须将它序列化到新的AppDomain中。这只是一堆开销,不如从磁盘加载它,反正它在那里。它已经在记忆中。文件系统缓存的内存。加载它会非常快,因为它实际上并不需要从磁盘读取。

0

CompilCode方法来自哪里呢?似乎是这是最重要的部分。你决定放弃它?

+0

'CompileCode'方法与问题并不紧密相关,即如何生成源代码,创建程序集并在运行时将其加载到'AppDomain'中。我意识到我最初的问题可能不是对我的问题的完全准确的描述,但是当我收到反馈意见并做了更多研究时,它改进了问题的范围和定义。具体来说,我尝试执行的操作顺序。在接受的答案中的文章澄清了我需要采取的方法,并帮助我解决了我的问题。 – 2012-11-12 14:35:26

相关问题