title: How can I use CodeDOM to create and load an assembly in an AppDomain?
body: <p>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.</p>
  
  <p>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 <em>within</em> the AppDomain.</p>
  
  <p>This example (<a href="http://www.west-wind.com/presentations/dynamicCode/DynamicCode.htm" rel="noreferrer">DynamicCode</a>) 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).</p>
  
  <p>Can anyone point me to an example of how to do this?</p>
  
  <p>Any help would be greatly appreciated.</p>
  
  <p>I've included some excerpts from my code so you can all get a feel for what I have so far:</p>
  
  <pre><code>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;
  }
  </code></pre>
  
  <p>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.</p>