|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionThis program compiles a piece of code in memory and runs it dynamically, so you can test some C# or VB.NET code without having to create a new project or solution. BackgroundVery often, we need test a piece of code ( C# or VB.NET ). In .NET environment, we use "csc" or "vbc" command; In VS.NET, we create a new project or solution, and create many other files. Both of them are tedious, especially when we test a simple program. One way is produced by jconwell, "Dot Net Script". He uses XML files ( named "dnml" ) which include C# or VB code. In that method, a dnml file is parsed and the code is compiled in memory. That's a good idea! However, it is a little inconvenience because it needs to build a new file. Here we provide a tool based on his work. The tool has these characters:
Using the toolAs the picture blow shows, press button "Open..." can Open C# or VB.NET file; press button "Paste" to paste code from clipboard to text area; check box "C#" means if the code is C# language; the text box is filled with entry point ( a static method in C# or a shared
How it woksThe main class of the program is public CompileEngine( string code, LanguageType language, string
entry )
{
this.SourceCode = code;
this.Language = language;
this.EntryPoint = entry;
}
public void Run()
{
ClearErrMsgs();
string strRealSourceCode = PrepareRealSourceCode();
Assembly assembly = CreateAssembly( strRealSourceCode );
CallEntry( assembly, EntryPoint );
DisplayErrorMsg();
}
private string PrepareRealSourceCode()
{
string strRealSourceCode = "";
// add some using(Imports) statements
string strUsingStatement = "";
if( Language == LanguageType.VB )
{
string [] basicImportsStatement = {
"Imports Microsoft.VisualBasic",
"Imports System",
"Imports System.Windows.Forms",
"Imports System.Drawing",
"Imports System.Data",
"Imports System.Threading",
"Imports System.Xml",
"Imports System.Collections",
"Imports System.Diagnostics",
};
foreach( string si in basicImportsStatement )
{
if( SourceCode.IndexOf( si ) < 0 )
strUsingStatement += si + "\r\n";
}
}
strRealSourceCode = strUsingStatement + SourceCode;
// for VB Prog, Add Main(), So We Can Run It
if( Language == LanguageType.VB && EntryPoint == "Main" &&
strRealSourceCode.IndexOf( "Sub Main(") < 0 )
{
try
{
int posClass = strRealSourceCode.IndexOf( "Public Class ")+
"Public Class ".Length;
int posClassEnd = strRealSourceCode.IndexOf( "\r\n", posClass );
string className = strRealSourceCode.Substring( posClass,
posClassEnd - posClass );
int pos = strRealSourceCode.LastIndexOf( "End Class");
if( pos > 0 )
strRealSourceCode = strRealSourceCode.Substring( 0, pos ) + @"
Private Shared Sub Main()
" + "Dim frm As New " + className + "()" + @"
If TypeOf frm Is Form Then frm.ShowDialog()
End Sub
" + strRealSourceCode.Substring( pos );
}
catch{}
}
return strRealSourceCode;
}
CreateAssembly compile the source code and make assembly in memory.
// 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)
{
//Create an instance whichever code provider that is needed
CodeDomProvider codeProvider = null;
if (Language == LanguageType.CSharp )
codeProvider = new CSharpCodeProvider();
else if( Language == LanguageType.VB )
codeProvider = new VBCodeProvider();
//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 = false;
// add some basic references
compilerParams.ReferencedAssemblies.Add( "mscorlib.dll");
compilerParams.ReferencedAssemblies.Add( "System.dll");
compilerParams.ReferencedAssemblies.Add( "System.Data.dll" );
compilerParams.ReferencedAssemblies.Add( "System.Drawing.dll" );
compilerParams.ReferencedAssemblies.Add( "System.Xml.dll" );
compilerParams.ReferencedAssemblies.Add(
"System.Windows.Forms.dll" );
if( Language == LanguageType.VB )
{
compilerParams.ReferencedAssemblies.Add(
"Microsoft.VisualBasic.dll" );
}
//actually compile the code
CompilerResults results = compiler.CompileAssemblyFromSource(
compilerParams,
strRealSourceCode );
//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
{
mi.Invoke(null, null);
}
return;
}
}
}
catch (Exception ex)
{
}
}
In the
private void btnRun_Click(object sender, System.EventArgs e)
{
// we use a new thread to run it
new Thread( new ThreadStart( RunTheProg ) ).Start();
}
private void RunTheProg()
{
string code = txtSource.Text.Trim();
LanguageType language = chkIsCSharp.Checked ?
LanguageType.CSharp : LanguageType.VB;
string entry = txtEntry.Text.Trim();
if( code == "" ) return;
if( entry == "" ) entry = "Main";
CompileEngine engine = new CompileEngine( code, language, entry );
engine.Run();
}
Some things that can improveIn the AcknowledgementThanks jconwell, VictorV, George Orwell, Eric Astor and other friends, they show me many excellent works on this topic, such as Dot Net Script, SnippetCompiler, Runtime Compilation.
|
||||||||||||||||||||||