Yeah the nice thing about Reflection is that its really easy to run C# code from a string in memory. Its literally only a few lines of code:
using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.CSharp;
public static bool Eval_CS_Code(string code, out object retVal)
{
retVal = null;
if (String.IsNullOrEmpty(code))
{
return false;
}
// Our C# compiler.
CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");
// Our C# compiler parameters
CompilerParameters compiler_parameters = new CompilerParameters();
// Set our compiler to work in memory.
compiler_parameters.GenerateInMemory = true;
// Reference some common DLL's..
foreach (string dll in new string[] {
"System.dll",
"System.Data.dll",
"System.Xml.dll",
"System.Windows.Forms.dll"
}// End array
)// End start of foreach
{
compiler_parameters.ReferencedAssemblies.Add(dll);
}// End foreach
// Shove code to run inside of a temp class/method
string[] tmpApp = new string[]
{
"using System;",
"public class Program {",
"public static void Main() {",
code,
"}",
"}",
""
};
// Set new statement now that.
code = String.Join(Environment.NewLine, tmpApp);
// Compile source..
CompilerResults results = compiler.CompileAssemblyFromSource(compiler_parameters, code);
// Did our compile go fubar?
if (results == null)
{
Console.WriteLine("Compiler results are null.");
return false;
}
if (results.Errors.Count > 0)
{
Console.WriteLine("Compile had errors:");
int i = 0;
while (i < results.Errors.Count)
{
Console.WriteLine("Error {0}: {1} on line {2}.",
results.Errors<i>.ErrorNumber,
results.Errors<i>.ErrorText,
results.Errors<i>.Line - 3 // Change index since we edit the code they use.
);
i++;
}
return false;
}
Assembly assembly = results.CompiledAssembly;
Type et = assembly.GetType("Program", false, true);
if (et == null)
{
Console.WriteLine("GetType failed. User should never see this.");
return false;
}
// C# does not support the style of binding we would love to have..
object evalObj = Activator.CreateInstance(et);
// Not an error that should happen.
if (evalObj == null)
{
Console.WriteLine("Could not activate object from source.");
return false;
}
// Invoke our created function using the entry point we set above.
retVal = et.InvokeMember(
"Main",
BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Static,
null,
evalObj,
new object[] { }
);
/* Fix the bug here.*/
return true;
}
.. There you go, everything you need to run C# scripts..
Oh and for the people blindly copy-and-pasting (it looks like this thread gets a lot of hits) keep in mind that yes, my code above does have a hidden bug in it just for you... and learning about it will be half the fun of using that code *grin*
I was not going to say anything, but I realized not saying anything may have been cruel..