Scripting
1,979
3
Advertisement
Scripting with .NET is unbelievably easy. [grin]
I wanted to add scripting support to Brass, and have added it using .NET's excellent powers of reflection and its System.CodeDom.Compiler namespace.
The first thing I need to do is find out which language the source script is written in. I use the extension to check for this.
Now that we have a compiler, we just set some settings, add some references, then compile the source files:
And that's it! In my case I now pass any errors back up to the assembler, and exit if there were any errors:
Now the task is passed on to reflection; I go through the compiled assembly, hunt down methods and wrap them up for use as native Brass functions and/or directives.
I've used this technique in the release of my PAL demo; a C# script file is used to encode an image to the 18x304 resolution and format required by the routine.
I wanted to add scripting support to Brass, and have added it using .NET's excellent powers of reflection and its System.CodeDom.Compiler namespace.
The first thing I need to do is find out which language the source script is written in. I use the extension to check for this.
string ScriptFile = ...; // Name of main script file to compile.CodeDomProvider Provider = null;// Get the extension (eg "cs")string Extension = Path.GetExtension(ScriptFile).ToLowerInvariant();if (Extension.Length > 0 && Extension[0] == '.') Extension = Extension.Substring(1);// Hunt through all available compilers and dig out one with a matching extension.foreach (CompilerInfo Info in CodeDomProvider.GetAllCompilerInfo()) { if (Info.IsCodeDomProviderTypeValid) { CodeDomProvider TestProvider = Info.CreateProvider(); if (TestProvider.FileExtension.ToLowerInvariant() == Extension) { Provider = TestProvider; break; } }}if (Provider == null) throw new CompilerExpection(source, "Script language not supported.");Now that we have a compiler, we just set some settings, add some references, then compile the source files:
string[] ScriptFiles = ...; // Array of source file name(s) to compile.// Compiler settings:CompilerParameters Parameters = new CompilerParameters();Parameters.GenerateExecutable = false; // Class lib, not .exeParameters.GenerateInMemory = true;// Add references:Parameters.ReferencedAssemblies.Add("System.dll");Parameters.ReferencedAssemblies.Add("Brass.exe");// Compile!CompilerResults Results = Provider.CompileAssemblyFromFile(Parameters, ScriptFiles);And that's it! In my case I now pass any errors back up to the assembler, and exit if there were any errors:
// Errors?foreach (CompilerError Error in Results.Errors) { Compiler.NotificationEventArgs Notification = new Compiler.NotificationEventArgs(compiler, Error.ErrorText, Error.FileName, Error.Line); if (Error.IsWarning) { compiler.OnWarningRaised(Notification); } else { compiler.OnErrorRaised(Notification); }}// Do nothing if there were errors.if (Results.Errors.HasErrors) return;Now the task is passed on to reflection; I go through the compiled assembly, hunt down methods and wrap them up for use as native Brass functions and/or directives.
// Grab the public classes from the script.foreach (Type T in Results.CompiledAssembly.GetExportedTypes()) { // ...}I've used this technique in the release of my PAL demo; a C# script file is used to encode an image to the 18x304 resolution and format required by the routine.

Advertisement
Advertisement
Advertisement
Discussion