Right now I'm working on a project, and the team wants a way to write code and edit it without having to recompile the whole project, so I've decided to try and implement a scripting engine.
Having implemented Lua into C++ before, I wasn't an entire newbie to implementing scripting capabilities into projects. However, we wanted to try and implement straight C# using the Microsoft.CSharp namespace, combined with System.Reflection that was already built in to C#.
So having hearing about this, I poked about in docs and I've come up with a prototype that ALMOST works - but doesn't quite.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
namespace Scripting
{
class Program
{
static void Main(string[] args)
{
StringBuilder builder = new StringBuilder();
builder.Append("using System;");
builder.Append("using Scripting;");
builder.Append("class MyScript : IScript");
builder.Append("{");
builder.Append(" string ScriptName");
builder.Append(" {");
builder.Append(" get { return \"My Script\"; }");
builder.Append(" }");
builder.Append(" public bool Initialize()");
builder.Append(" {");
builder.Append(" Console.WriteLine(\"Hello, World!\");");
builder.Append(" return true;");
builder.Append(" }");
builder.Append("}");
CSharpCodeProvider provider = new CSharpCodeProvider();
CompilerParameters param = new CompilerParameters(new string[] { "System.dll", "Scripting.dll" });
param.GenerateInMemory = true;
param.GenerateExecutable = true;
CompilerResults result = provider.CompileAssemblyFromSource(param, builder.ToString());
if (result.Errors.Count > 0)
{
foreach (CompilerError error in result.Errors)
Console.WriteLine(error);
Console.ReadKey();
return;
}
}
}
}
The issue I have at the moment is that I want to be able to reference my interface - IScript.cs (which is inside the Scripting namespace and thus, the current assembly) - so that scripts written and parsed in the compiler can access it. Obviously, I added Scripting.dll as a parameter, but it doesn't seem to be able to be accessed for some reason or another. I am running it in debug so this could be cause for some major facepalmage. What do?
Is there a way to reference the current assembly and pass it to CompilerParameters? Or am I royally screwed / should I rely on creating an assembly for script objects / etc?
It's probably looking in the wrong directory.
Pass typeof(Program).Assembly.CodeBase
to pass the full path.
You can get the executable and pass it to the CompilerParameters:
string exeName = Assembly.GetEntryAssembly().Location;
param.ReferencedAssemblies.Add(exeName);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With