Generating .net assemblies from within .net isn't so hard. Here is an example, I need to flesh it out a fair bit but its pretty easy to follow.
I have used this approach for generating code in some of my apps.
/// <summary> /// Creates an executable file from the supplied <paramref name="code"/>. /// </summary> /// <param name="code">The code.</param> /// <param name="referencedAssemblies">The referenced assemblies (apart from "system.dll").</param> /// <param name="exeName">Name of the exe, e.g. "HelloWorld".</param> /// <returns>The path of the new exe.</returns> public static string CreateExe(string code, string mainClass, string[] referencedAssemblies, string exeName) { // Create an instance of the CSharpCodeProvider to compile the C# code CodeDomProvider codeProvider = new CSharpCodeProvider(); //create the language specific code compiler //ICodeCompiler compiler = codeProvider.CreateCompiler(); //add compiler parameters CompilerParameters compilerParams = new CompilerParameters(); compilerParams.GenerateExecutable = true; // .exe compilerParams.OutputAssembly = exeName + ".exe"; compilerParams.CompilerOptions = "/optimize"; compilerParams.GenerateInMemory = false; // will get written to disk compilerParams.IncludeDebugInformation = false; // i.e. release code compilerParams.TempFiles = new TempFileCollection(".", true); compilerParams.MainClass = mainClass; compilerParams.ReferencedAssemblies.Add("system.dll"); if (referencedAssemblies != null) { foreach (string reference in referencedAssemblies) { compilerParams.ReferencedAssemblies.Add(reference); } } //actually compile the code CompilerResults results = codeProvider.CompileAssemblyFromSource(compilerParams, code); //Do we have any compiler errors if (results.Errors.Count > 0) { string errors = string.Empty; foreach (CompilerError error in results.Errors) errors += error.ToString() + Environment.NewLine; throw new Exception(errors); } return results.PathToAssembly; }
Call the function in a method similar to:
static void Main(string[] args) { // I appoligize in advance for this program: string sourceCode = @" using System; namespace HelloWorld { public class Program { static void Main(string[] args) { Console.WriteLine(""Sorry, but hello world...""); } } }"; string path = AssemblyUtility.CreateExe( sourceCode, "HelloWorld.Program", null, "HelloWorld"); Console.WriteLine("New exe at: " + path); }
Basically this will create an executable file called "HelloWorld.exe" (I hate that example!).
In the code above I chose to leave the temporary files in the build directory [compilerParams.TempFiles = new TempFileCollection(".", true)]. If you run the sample application you will fild the following files created:
Example Source Code: (TODO)
Not so hard? Why do I need the CSharpCodeProvider etc? The real power of code compilation comes when you start building DLL's in memory [compilerParams.GenerateInMemory = true]. You can then get the resulting compiled Assembly at runtime from the compiler result [results.CompiledAssembly].
If you generate a new assembly on the fly you can use it one of 2 ways (or you can save it to disk and link to it etc.)
Method 1 - Use reflection. Upside, extreemly flexible. Downside, slow.
Method 2 - Have your generated code implement an interface or inherit from a base clase that the running code already knows about. This is my prefered method. Its far more effecient. How?
BaseClass CreateClassInstance(Assembly assemblyReference, string className) { return assemblyReference.CreateInstance(className) as BaseClass; }
When I get around to it I will post some updated code for these extentions.