I have these scripting tools that nobody wants: Lychen and LychenBASIC. (That's not counting the others I have in my github repository that are DOS-specific.) I don't care, really, as these tools are just for me to experiment with.
So today I extended Lychen and LychenBASIC so that they can load assemblies during the running of a script. ClearScript makes this quite easy through their .Script
property, which can be used to expose C#-side items directly into the V8, JScript and VBScript engines.
In my Action delegate gives print to VBScript article, I demonstrated the use of the .Script
mechanism to add a print
command to LychenBASIC. I have now done the same to Lychen (which targets V8) and could conceivably do the same to the in-house tool, RulesetRunner (which targets JScript).
So here it is adding print
to Lychen
v8.Script.print = (Action<object>)Console.WriteLine;
v8.Script.attach = (Action<string, string>)Attach;
So what's this attach
about? Well, it's the hook to the function to load dotnet assemblies during the running of a script.
Attach
is, according to the cast at the front, an Action
that takes two strings. The first is the path to the dotnet dll we want to attach. The second is an optional symbol to which the dll's PropertyBag is attached. Ordinarily, one might get away with leaving that second parameter as an empty string, but occasionally we need something in there. I'll discuss why a little later.
So the implementation of Attach is as follows:
private static void Attach(string dllPath, string name = "")
{
var htc = new HostTypeCollection();
try
{
var assem = Assembly.LoadFrom(dllPath);
htc.AddAssembly(assem);
if (name.Length == 0)
{
name = assem.FullName.Split(',')[0];
}
v8.AddHostObject(name, htc);
Console.WriteLine($"Attached {name}");
}
catch (FileNotFoundException fnfe)
{
Console.WriteLine(fnfe.Message);
}
catch (ReflectionTypeLoadException ctle)
{
Console.WriteLine(ctle.Message);
}
}
With that compiled into the Lychen and LychenBASIC binaries, we now have an attach
procedure that makes the following possible:
attach "C:\programdata\lychen\newtonsoft.json.dll", "J"
a = J.Newtonsoft.Json.jsonconvert.deserializeobject("{a:1,b:2,c:{d:1}}")
print a.c.d
VBScript ignores case, and after a while in VBScript, JavaScript's addiction to case-sensitivity really takes some getting used to.
Now something similar in Lychen (V8)
attach("C:\\programdata\\lychen\\newtonsoft.json.dll", "J");
var a = J.Newtonsoft.Json.JsonConvert.SerializeObject({a:1,b:2,c:{d:1}});
print(a);
The reason why the above specifies a name to attach the Newtonsoft.Json's PropertyBag to is that if you don't, my ClearScript code will create a name derived from the assembly's FullName and in this case that name is "Newtonsoft.Json". This confuses the host. The "." implies that there's a Newtonsoft
PropertyBag with a Json
property. If you code Newtonsoft.Json.JsonConvert ...
the host crashes. I should do something about this, but at this point the solution is just to provide an explicit attachment point.
Delegates offer a lot of scope for extension in dotnet applications. Expect to see more about this subject as I continue to experiment on Lychen and LychenBASIC.
Top comments (0)