OK, as OP expressed interest in my alternative way of working with dynamically compiled assemblies, I'm starting to sketch the design.
Introduction: I used to develop some designs for adding assemblies dynamically or during run-time. One option is to add assemblies from executable files. Such assemblies could be loaded during run-time once and until the end of the run-time of the host application, which is easy (I call it plug-in architecture) or periodically unloaded or loaded, which is more difficult, because there is no way to unload a loaded assembly — conceptually, by .NET design, so
System.AppDomain
should be used (let's call it dynamic modular design). Another opportunity is to generate assembly from code DOM into host's memory. Let's call it IDE design. I used IDE design to create a conventional C# (or any other .NET language-based calculator) and also a symbolic calculator, a part of my Computer Algebra System (CAS) calculator. As the calculator design does not disclose my know-how on the CAS, I can share it. Naturally, the IDE design should only work with Application Domains, because the IDE should allow for unlimited number of re-compilation. In essence, the host application provides the host for building and running small applications (let's call them Applets) in the same process as the host, but in different Application Domain and thread(s).
Interfaces with plug-ins or Applets and System.AppDomain
: Take a look at my recent Answer to a different Question:
Create WPF Application that uses Reloadable Plugins...[
^]. Please understand that some more advanced aspect of this discussion are highly controversial and needs some development. Here we only need to discuss the IDE design which is much more certain and well-defined compared to the very indeterminate requirements of Ven's project which is probably in an early inception phase. Important point in this reference for IDE design is: how to define interface with the plug-in (in our case it will be the Applet, so mentally replace "plug-in interface" with "Applet interface"), how to recognize and instantiate the entry class in the Applet by the host's code and how to work across the boundary beteen different Application Domains. Let's assume it is more or less clear.
Applet hosting interface: Lets go back to IDE design. The Applet hosting interface should do something like that: it should be able to get some source code of the future Applet in the form of one or more strings each representing the input file. Code DOM has the options to compile such set of source codes. Another option to be used is to compile it into memory. The result of compilation should (errors, code line numbers, etc.) should be delivered to the host through the Application Domain boundary. Another method of the Applet hosting interface would be to "run" some method of the complied applet and re-direct output in some way accessible by the host. Let's consider such output.
Applet output: This way should be designed, but the main principle is working via IPC, because the data should be passed via Application Domain boundary (from Applet's Application Domain to host Application Domain), and also dispatched to the host's UI thread. In my projects, the output was simply a string (in one project representing HTML passed to Web browser control). For such simple data transfer a simplified method of
System.AppDomain
can be used. For more complex and time consuming data transfer process a blocking queue based on transport IPC should be used: WCF or remoting, based on Windows named pipes. The dispatching of events to the UI thread should be done entirely on the host Application Domain side, see:
Control.Invoke() vs. Control.BeginInvoke()[
^],
Problem with Treeview Scanner And MD5[
^].
Applet interface: How Applet hosting interface should identify what Applet method to run. It should be defined as a special Applet interface and, after compilation, instantiated by the host (on Applet Application Domain side). It is done using the same principles described in the section "Interfaces with plug-ins or Applets and
System.AppDomain
".
General order of operation: This is the main cycle of the host application. The user types the code of applet (it can be simplified by adding some common constructs automatically) or load the code from external file(s). The host should have a singleton (
http://en.wikipedia.org/wiki/Singleton_pattern[
^]) object of the type
System.AppDomain
initialized lazily (
http://en.wikipedia.org/wiki/Lazy_evaluation[
^]). If previously created instance exists, it should be unloaded. This is a whole point of using Application Domains, otherwise inability to unload any assemblies would created a strong memory leak. New Application Domain is created, source code and options (in particular, ID of computer language!) delivered to the instance of the Applet host through the Application Domain boundary.
AppDomain.GetData/SetData
would work fine for these purposes. Code is compiled into memory in the Applet's Application Domain, errors delivered back to the host. The errors can be presented to the host's UI in the same way as in Visual Studio. If the build is successful, the new Assembly appears in the memory space of the Applet's Application domain. Applet host interface try to identify entry point object according the the schema described above, using Applet interface. If this procedure is failed, the status is delivered back to the host's Application Domain and presented in the UI. If the reference to the Applet host is obtained (entry class implementing Applet interface instantiated), Applet entry point is run, output is delivered to the host. The compilation and run of Applet should be done in the separate thread created in the Applet's Application host from the very beginning. The host need a way abort this thread through the Application Domain boundary. What is good, any problems of incomplete reclaiming of any resources in the Applet's Application Domain and not critical, because this domain will be unloaded in cycle. When Applet interface code run cycle is finished, the event is delivered through the Application Domain boundary to the host. The host UI enables the user to start a new compile/run cycle.
—SA