How can I use CodeDOM to create and load assemblies in AppDomain?

I am working on a project that will use CodeDOM to create a class that evaluates a custom expression, creates an assembly for this class, and loads the assembly. Since there may be a fair number of user expressions, I would like to first create an AppDomain, create / load and execute a CodeDOM to build inside that AppDomain, and then unload the AppDomain.

I searched quite a lot and found many examples of how to load an existing assembly in AppDomain, but I cannot find it, which shows me how to create an assembly from AppDomain.

This example ( DynamicCode ) creates an assembly using CodeDOM and then loads it into AppDomain, however, the author generates the assembly to disk. I would rather create an assembly in memory, so I donโ€™t need to control the cleanup of the generated assemblies. (although this creates a dll file in the temp folder).

Can someone give me an example of how to do this?

Any help would be greatly appreciated.

I added some excerpts from my code so that you can all understand what I still have:

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; } 

I believe that these code snippets show the main functions of my project. Now all I have to do is wrap it in my own AppDomain.

+4
source share
4 answers

I found the answer I was looking for at http://www.softwareinteractions.com/blog/2010/2/7/loading-and-unloading-net-assemblies.html . He has a good article that details how to create an AppDomain and load an assembly as a plugin. I followed his example and was able to create an AppDomain, create a proxy for my ExpressionEvaluator factory class, and successfully call it and get the results.

+2
source

The problem with the chicken and the egg. You need a small boot buffer assembly that you can load in the new AppDomain. With a well-known class that loads the CodeDom assembly and runs it.

Doing this with GenerateInMemory is pretty pointless; you have to serialize it in the new AppDomain. It's just a bunch of overhead, it can also load it from disk, it is all the same. And this is already in my memory. File system cache The download will be very fast, since in fact it does not need to be read from disk.

+3
source

Just use AssemblyBuilderAccess.Run when you define a dynamic assembly. http://msdn.microsoft.com/en-us/library/system.reflection.emit.assemblybuilderaccess.aspx

Dynamic assembly can be performed but not saved.

+1
source

Where does the CompilCode method come from all this? This seems to be the most important part. And you decided to leave it?

0
source

All Articles