|
/* Originaly found the code here
* A tool for dynamic compile and run of C# or VB.NET code
* http://www.codeproject.com/dotnet/DynamicCompileAndRun.asp
* By dstang2000.
*/
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Reflection;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using Microsoft.VisualBasic;
namespace SubSonic.CodeGenerator
{
public class CompileEngine
{
public CompileEngine( string code )
{
this.SourceCode = code;
}
public CompileEngine( string code, ICodeLanguage language, string entry )
{
this.SourceCode = code;
this.Language = language;
this.EntryPoint = entry;
}
public void Run()
{
ClearErrMsgs();
//Utilities.Utility.WriteTrace("Building Assembly");
Assembly assembly = CreateAssembly(SourceCode);
if (assembly == null) {
Utilities.Utility.WriteTrace("Assembly is NULL - that means there's an error. Serving up Exception...");
//get the error message and throw an Exception
string sMessage = "Error generating template code: this happens because the rendering code (not that of the template) " + Environment.NewLine +
" has encountered an error. Most likely it has to do with a Primary Key - make sure one is defined for this table." + Environment.NewLine +
" Other possibilities revolve around reserved words and naming... Here's some more detail:" + Environment.NewLine +
this.errMsg.ToString();
throw new Exception(sMessage);
} else {
Utilities.Utility.WriteTrace("Compiling Assembly Code... Good to Go...");
CallEntry(assembly, EntryPoint);
}
}
public string OutputText;
//Holds the main source code that will be dynamically compiled and executed
internal string SourceCode = string.Empty;
//Holds the method name that will act as the assembly entry point
internal string EntryPoint = "Main";
//A list of all assemblies that are referenced by the created assembly
internal ArrayList References = new ArrayList();
//A flag the determines if console window should remain open until user clicks enter
//internal bool WaitForUserAction = true;
//Flag that determines which languae to use
internal ICodeLanguage Language = new CSharpCodeLanguage();
// compile the source, and create assembly in memory
// this method code is mainly from jconwell,
// see http://www.codeproject.com/dotnet/DotNetScript.asp
private Assembly CreateAssembly(string strRealSourceCode)
{
if (strRealSourceCode.Length == 0)
{
LogErrMsgs("Error: There was no CS script code to compile");
return null;
}
//Create an instance whichever code provider that is needed
CodeDomProvider codeProvider = Language.CreateCodeProvider();
//create the language specific code compiler
//ICodeCompiler compiler = codeProvider.CreateCompiler();
//add compiler parameters
CompilerParameters compilerParams = new CompilerParameters();
compilerParams.CompilerOptions = "/target:library"; // you can add /optimize
compilerParams.GenerateExecutable = false;
compilerParams.GenerateInMemory = true;
compilerParams.IncludeDebugInformation = true;
// add some basic references
compilerParams.ReferencedAssemblies.Add( "mscorlib.dll");
compilerParams.ReferencedAssemblies.AddRange((string[])References.ToArray(typeof(string)));
//add any aditional references needed
//foreach (string refAssembly in References)
//{
// try
// {
// string trimchar = Environment.NewLine;
// string trimmedref = refAssembly.Trim(trimchar.ToCharArray());
// trimmedref = trimmedref.Trim();
// if(trimmedref.Length > 0)
// compilerParams.ReferencedAssemblies.Add(trimmedref);
// }
// catch { }
//}
//actually compile the code
CompilerResults results = codeProvider.CompileAssemblyFromSource(compilerParams, strRealSourceCode);
//Do we have any compiler errors
if (results.Errors.Count > 0)
{
foreach (CompilerError error in results.Errors)
LogErrMsgs("Compile Error: " + error.ErrorText );
return null;
}
//get a hold of the actual assembly that was generated
Assembly generatedAssembly = results.CompiledAssembly;
//return the assembly
return generatedAssembly;
}
// invoke the entry method
// this method code is mainly from jconwell,
// see http://www.codeproject.com/dotnet/DotNetScript.asp
private void CallEntry(Assembly assembly, string entryPoint)
{
try
{
//Use reflection to call the static Main function
Module[] mods = assembly.GetModules(false);
Type[] types = mods[0].GetTypes();
foreach (Type type in types)
{
MethodInfo mi = type.GetMethod(entryPoint,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
if (mi != null)
{
if( mi.GetParameters().Length == 1 )
{
if( mi.GetParameters()[0].ParameterType.IsArray )
{
string [] par = new string[1]; // if Main has string [] arguments
mi.Invoke(null, par);
}
}
else
{
OutputText = (string)mi.Invoke(null, null);
}
return;
}
}
}
catch
{
//LogErrMsgs("Error: An exception occurred", ex);
//throw ex;
//if there's an error here, it's not a bad template - that would
//be caught above. It's because the template, as designed, won't work
//there's generally only one cause - NO PRIMARY KEY
Utilities.Utility.WriteTrace("!!!!!!!!!! No primary key defined for this table - ####### ABORTED #######");
//swallow it
}
}
internal StringBuilder errMsg = new StringBuilder();
internal void LogErrMsgs(string customMsg)
{
LogErrMsgs(customMsg, null);
}
internal void LogErrMsgs(string customMsg, Exception ex)
{
//put the error message into builder
errMsg.Append("\r\n").Append(customMsg).Append(Environment.NewLine);
//get all the exceptions and add their error messages
while (ex != null)
{
errMsg.Append("\t").Append(ex.Message).Append(Environment.NewLine);
ex = ex.InnerException;
}
}
internal void ClearErrMsgs()
{
errMsg.Remove( 0, errMsg.Length );
}
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.